package com.ccp.dev.workflow.service;

import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.db.datasource.DataSourceUtil;
import com.ccp.dev.core.basic.table.TableModel;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.basic.web.query.QueryFilter;
import com.ccp.dev.core.util.*;
import com.ccp.dev.form.dao.FormDefDao;
import com.ccp.dev.form.dao.FormRightsDao;
import com.ccp.dev.form.dao.FormTableDao;
import com.ccp.dev.form.model.FormDef;
import com.ccp.dev.form.model.FormRights;
import com.ccp.dev.form.model.FormTable;
import com.ccp.dev.form.service.FormDefService;
import com.ccp.dev.form.service.FormTableService;
import com.ccp.dev.form.util.PlatformType;
import com.ccp.dev.form.xml.form.BpmFormDefXml;
import com.ccp.dev.form.xml.table.BpmFormTableXml;
import com.ccp.dev.form.xml.util.MsgUtil;
import com.ccp.dev.system.dao.GlobalTypeDao;
import com.ccp.dev.system.model.*;
import com.ccp.dev.system.service.*;
import com.ccp.dev.workflow.bpmutil.BPMN20Util;
import com.ccp.dev.workflow.bpmutil.BpmUtil;
import com.ccp.dev.workflow.dao.*;
import com.ccp.dev.workflow.model.*;
import com.ccp.dev.workflow.model.bpm.BpmFormResult;
import com.ccp.dev.workflow.model.bpm.BpmNodeSign;
import com.ccp.dev.workflow.service.bpm.BpmRunLogService;
import com.ccp.dev.workflow.xml.ActDefModelXml;
import com.ccp.dev.workflow.xml.ActDefModelXmlList;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
import org.flowable.editor.language.json.converter.util.CollectionUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.BaseExecutionListener;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.engine.impl.persistence.entity.ByteArrayEntityImpl;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.DeploymentBuilder;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.ui.common.service.exception.BadRequestException;
import org.flowable.ui.common.service.exception.InternalServerErrorException;
import org.flowable.ui.common.util.XmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * ClassDescribe:
 * 流程模型业务层
 * @author :jiayueqiao
 * Date: 2019-05-15
 * Since:1
 * To change this template use File | Settings | File Templates.
 */
@Service
public class ActDefModelService extends BaseService<ActDefModel> {
    private static final Logger LOGGER = LoggerFactory.getLogger(ActDefModelService.class);

    @Resource
    private ActDefModelDao actDefModelDao;
    @Resource
    private ActGeByteArrayDao actGeByteArrayDao;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private ActModelImageService actModelImageService;
    @Resource
    private BpmnXmlService bpmnXmlService;
    @Resource
    private ListenerService listenerService;
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private BpmNodeSetService bpmNodeSetService;
    @Resource
    private BpmNodeSetDao bpmNodeSetDao;
    @Resource
    private BpmNodeButtonDao bpmNodeButtonDao;
    @Resource
    private BpmDefVarDao bpmDefVarDao;
    @Resource
    private BpmNodeScriptDao bpmNodeScriptDao;
    @Resource
    private BpmNodeUserDao bpmNodeUserDao;
    @Resource
    private BpmUserConditionDao bpmUserConditionDao;
    @Resource
    private SpringProcessEngineConfiguration springProcessEngineConfiguration;
    @Resource
    private FormDefDao formDefDao;
    @Resource
    private FormTableDao formTableDao;
    @Resource
    private BpmService bpmService;
    @Resource
    private BpmNodeRuleDao bpmNodeRuleDao;
    @Resource
    private BpmNodeButtonService bpmNodeButtonService;
    @Resource
    private FormRightsDao formRightsDao;
    @Resource
    private BpmNodeMessageDao bpmNodeMessageDao;
    @Resource
    private BpmFormRunDao bpmFormRunDao;
    @Resource
    private BpmProStatusDao bpmProStatusDao;
    @Resource
    private TaskForkService taskForkService;
    @Resource
    private TaskOpinionDao taskOpinionDao;
    @Resource
    private BpmDefAuthorizeActDao bpmDefAuthorizeActDao;
    @Resource
    private ExecutionStackDao executionStackDao;
    @Resource
    private TaskSignDataDao taskSignDataDao;
    @Resource
    private ExecutionDao executionDao;
    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private PositionService positionService;
    @Resource
    private BpmDefAuthorizeService bpmDefAuthorizeService;
    @Resource
    private ProcessRunService processRunService;
    @Resource
    private FormHandlerService formHandlerService;
    @Resource
    private FormTableService formTableService;
    @Resource
    private BpmNodePrivilegeDao bpmNodePrivilegeDao;
    @Resource
    private TaskDao taskDao;
    @Resource
    private TaskReadService taskReadService;
    @Resource
    private BpmTaskExeService bpmTaskExeService;
    @Resource
    private BpmRunLogService bpmRunLogService;
    @Resource
    private ProcessCopyToService processCopyToService;
    @Resource
    private SysFileService sysFileService;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private FormDefService formDefService;
    @Resource
    private TaskReminderDao taskReminderDao;
    @Resource
    private BpmGangedSetDao bpmGangedSetDao;
    @Resource
    private BpmNodeSignDao bpmNodeSignDao;
    @Resource
    private BpmNodeSqlService bpmNodeSqlService;
    @Resource
    private BpmNewFlowTriggerService bpmNewFlowTriggerService;
    @Resource
    private NodeMsgTemplateService msgTemplateService;
    @Resource
    private TaskApprovalItemsService taskApprovalItemsService;
    @Resource
    private CommuReceiverService commuReceiverService;
    @Resource
    private GlobalTypeDao globalTypeDao;

    private BpmnJsonConverter bpmnJsonConverter = new BpmnJsonConverter();


    /**
     * 验证模型key
     * @param model   流程模型
     * @param key     模型key
     * @return 模型key验证封装类
     */
    public ModelKeyRepresentation validateModelKey(ActDefModel model, String key) {
        ModelKeyRepresentation modelKeyResponse = new ModelKeyRepresentation();
        modelKeyResponse.setKey(key);
        ActDefModel modelInfo = actDefModelDao.getByModelKey(key);
        if (null != modelInfo) {
            if (model == null || !(modelInfo.getId().equals(model.getId()) || modelInfo.getId().equals(model.getParentModelId()))) {
                modelKeyResponse.setKeyAlreadyExists(true);
                modelKeyResponse.setId(modelInfo.getId());
                modelKeyResponse.setName(modelInfo.getName());
            }
        }
        return modelKeyResponse;
    }

    /**
     * 转换模型数据为json字符串
     * @return 模型数据json对象
     */
    public ObjectNode createModelJson() {

        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.set("stencilset", stencilSetNode);
        ObjectNode propertiesNode = objectMapper.createObjectNode();
        propertiesNode.put("process_id", "newModel" + System.currentTimeMillis());
        propertiesNode.put("name", "newModel");
        editorNode.set("properties", propertiesNode);

        ArrayNode childShapeArray = objectMapper.createArrayNode();
        editorNode.set("childShapes", childShapeArray);
        ObjectNode childNode = objectMapper.createObjectNode();
        childShapeArray.add(childNode);
        ObjectNode boundsNode = objectMapper.createObjectNode();
        childNode.set("bounds", boundsNode);
        ObjectNode lowerRightNode = objectMapper.createObjectNode();
        boundsNode.set("lowerRight", lowerRightNode);
        lowerRightNode.put("x", 130);
        lowerRightNode.put("y", 193);
        ObjectNode upperLeftNode = objectMapper.createObjectNode();
        boundsNode.set("upperLeft", upperLeftNode);
        upperLeftNode.put("x", 100);
        upperLeftNode.put("y", 163);
        childNode.set("childShapes", objectMapper.createArrayNode());
        childNode.set("dockers", objectMapper.createArrayNode());
        childNode.set("outgoing", objectMapper.createArrayNode());
        childNode.put("resourceId", "startEvent1");
        ObjectNode stencilNode = objectMapper.createObjectNode();
        childNode.set("stencil", stencilNode);
        stencilNode.put("id", "StartNoneEvent");

        return editorNode;
    }

    /**
     * 创建新模型
     * @param model      模型封装类
     * @param editorJson 模型数据json串
     * @param createdBy  创建人
     * @return 新模型对象
     */
    @Transactional(rollbackFor = Exception.class)
    public ActDefModel createModel(ModelRepresentation model, String editorJson, SysUser createdBy) {
        ActDefModel newModel = new ActDefModel();
        if (StringUtil.isNotEmpty(model.getId())) {
            newModel.setId(model.getId());
        }
        newModel.setVersion(1);
        newModel.setTaskNameRule(ActDefModel.DEFAULT_SUBJECT_RULE);
        newModel.setStatus((short) 0);
        newModel.setName(model.getName());
        newModel.setModelKey(model.getKey());
        newModel.setTypeId(model.getCategory());
        newModel.setCreateTime(Calendar.getInstance().getTime());
        newModel.setCreateBy(createdBy.getUserId());
        newModel.setIsMain(ActDefModel.IS_MAIN);
        newModel.setDescription(model.getDescription());
        newModel.setModelEditorJson(editorJson);
        newModel.setUpdateTime(Calendar.getInstance().getTime());
        newModel.setUpdateBy(createdBy.getUserId());
        newModel.setTenantId(ContextUtil.getCurrentUserTenantId());
        //保存model
        persistModel(newModel, true);
        return newModel;
    }

    /**
     * 更新模型
     * @param model 模型对象
     * @param values 模型数据集合
     * @return 模型封装对象
     */
    @Transactional(rollbackFor = Exception.class)
    public ModelRepresentation updateModel(ActDefModel model, MultiValueMap<String, String> values) throws Exception{

        String name = values.getFirst("name");
        String key = values.getFirst("key").replaceAll(" ", "");
        String description = values.getFirst("description");
        String category = values.getFirst("category");
        //是否发布新版本
        String isNewVersionString = values.getFirst("newversion");
        //是否需要发布
        String needPublishString = values.getFirst("publish");
        //是否已经发布
        String hasDeployedString = values.getFirst("deployed");
        String newVersionComment = null;
        boolean newVersion = false;

        if (isNewVersionString != null) {
            newVersion = "true".equals(isNewVersionString);
            newVersionComment = values.getFirst("comment");
        }

        //设计图json数据
        String json = values.getFirst("json_xml");
        // 流程定义id
        String procDefId;
        ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(json);
        // 将editorJson转换成bpmnModel
        BpmnModel bpmnModel = bpmnJsonConverter.convertToBpmnModel(editorJsonNode);
        // 添加监听器
        addListenersToProcess(bpmnModel);
        // 将bpmnModel转成ObjectNode
        ObjectNode jsonNodes = bpmnJsonConverter.convertToJson(bpmnModel);

        ObjectNode propertiesNode = (ObjectNode) jsonNodes.get("properties");
        propertiesNode.put("process_id", key);
        propertiesNode.put("name", name);
        if (StringUtils.isNotEmpty(description)) {
            propertiesNode.put("documentation", description);
        }
        jsonNodes.set("properties", propertiesNode);
        //旧模型的id
        String oldModelId = model.getId();
        //更新模型
        model = saveModel(oldModelId, name, key, category, description, jsonNodes.toString(), newVersion,
                newVersionComment);

        // 如果需要部署则重新部署
        if (StringPool.TRUE.equals(needPublishString)) {
            deploy(model);
            saveOrUpdateSetting(model.getId(),oldModelId);
        } else if (StringPool.TRUE.equals(hasDeployedString)) {
            // 不需要部署，但是已经部署过的，直接修改资源表内容
            updateResource(model);
            procDefId = model.getProcDefId();
            NodeCache.clear(procDefId);
        }
        return new ModelRepresentation(model);
    }

    /**
     * 模型持久化
     * @param model 模型对象
     * @return 模型对象
     */
    @Transactional(rollbackFor = Exception.class)
    protected ActDefModel persistModel(ActDefModel model, boolean isNew) {

        if (StringUtils.isNotEmpty(model.getModelEditorJson())) {

            ObjectNode jsonNode;
            try {
                jsonNode = (ObjectNode) objectMapper.readTree(model.getModelEditorJson());
            } catch (Exception e) {
                LOGGER.error("Could not deserialize json model", e);
                throw new InternalServerErrorException("Could not deserialize json model");
            }

            // 图片二进制数据
            byte[] thumbnail = actModelImageService.generateThumbnailImage(model, jsonNode);
            if (thumbnail != null) {
                model.setThumbnail(thumbnail);
            }

            if (isNew) {
                actDefModelDao.add(model);
            }else {
                actDefModelDao.update(model);
            }
        }
        return model;
    }

    /**
     * 获取新模型
     * @param modelId 模型id
     * @param values 请求参数集合
     * @param modelRepresentation 模型封装对象
     * @return 模型对象
     */
    @Transactional(rollbackFor = Exception.class)
    public ActDefModel initModel(String modelId,MultiValueMap<String, String> values, ModelRepresentation modelRepresentation) throws Exception {

        String key = values.getFirst("key");
        String editorJson = values.getFirst("json_xml");
        String name = values.getFirst("name");
        String category = values.getFirst("category");
        String description = values.getFirst("description");

        // 将editorJson转换成bpmnModel
        ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(editorJson);
        BpmnModel bpmnModel = bpmnJsonConverter.convertToBpmnModel(editorJsonNode);
        // 添加监听器
        addListenersToProcess(bpmnModel);
        // 将bpmnModel转成ObjectNode
        ObjectNode jsonNodes = bpmnJsonConverter.convertToJson(bpmnModel);
        editorJson = jsonNodes.toString();

        //是否部署
        String publish = values.getFirst("publish");
        modelRepresentation.setCategory(category);
        modelRepresentation.setName(name);
        modelRepresentation.setKey(key);
        modelRepresentation.setDescription(description);
        modelRepresentation.setId(modelId);

        SysUser sysUser = (SysUser) ContextUtil.getCurrentUser();

        //保存模型对象
        ActDefModel newModel = createModel(modelRepresentation, editorJson, sysUser);

        // 是否需要部署
        if (StringPool.TRUE.equals(publish)) {
            deploy(newModel);
        }
        return newModel;
    }

    /**
     * 保存模型
     * @param modelId 模型id
     * @param name 模型名称
     * @param key 模型key
     * @param description 说明
     * @param editorJson 模型节点数据
     * @param newVersion 是否创建新版本
     * @param newVersionComment 新版本更改原因
     * @return 模型对象
     */
    @Transactional(rollbackFor = Exception.class)
    public ActDefModel saveModel(String modelId, String name, String key, String category, String description, String editorJson,
                           boolean newVersion, String newVersionComment) {

        SysUser currentUser = (SysUser) ContextUtil.getCurrentUser();
        //旧模型
        ActDefModel modelObject = actDefModelDao.getById(modelId);
        if (!newVersion) {
            //不发布新版
            modelObject.setUpdateTime(new Date());
            modelObject.setUpdateBy(currentUser.getUserId());
            modelObject.setName(name);
            modelObject.setModelKey(key);
            modelObject.setTypeId(category);
            modelObject.setDescription(description);
            modelObject.setModelEditorJson(editorJson);
            return persistModel(modelObject, false);
        } else {
            //发布新版
            String newModelId = UUIDUtils.getUUIDFor32();
            //将原来的模型设置为非主版本
            ActDefModel oldMainModel = actDefModelDao.getMainByModelKey(key);
            updateSubVersions(key,newModelId);
            //保存新模型
            modelObject.setVersion(oldMainModel.getVersion() + 1);
            modelObject.setUpdateTime(new Date());
            modelObject.setUpdateBy(currentUser.getUserId());
            modelObject.setName(name);
            modelObject.setModelKey(key);
            modelObject.setTypeId(category);
            modelObject.setDescription(description);
            modelObject.setModelEditorJson(editorJson);
            modelObject.setModelComment(newVersionComment);
            modelObject.setId(newModelId);
            return persistModel(modelObject, true);
        }
    }

    /**
     * 封装默认执行监听器
     * @return 执行监听器列表
     */
    private List<FlowableListener> defaultExecutionListeners(){
        List<FlowableListener> executionListeners = new ArrayList<>();
        //流程开始事件监听器
        FlowableListener startEventListener = listenerService.generateListener(BaseExecutionListener.EVENTNAME_START,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.EXECUTION_START_LISTENER);
        //流程结束事件监听器
        FlowableListener endEventListener = listenerService.generateListener(BaseExecutionListener.EVENTNAME_END,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.EXECUTION_END_LISTENER);
        executionListeners.add(startEventListener);
        executionListeners.add(endEventListener);
        return executionListeners;
    }

    /**
     *  封装默认任务监听器
     * @return 任务监听器列表
     */
    private List<FlowableListener> defaultTaskListeners() {
        List<FlowableListener> taskListeners = new ArrayList<>();
        FlowableListener taskCreateListener = listenerService.generateListener(TaskListener.EVENTNAME_CREATE,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.TASK_CREATE_LISTENER);
        FlowableListener taskDeleteListener = listenerService.generateListener(TaskListener.EVENTNAME_DELETE,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.TASK_DELETE_LISTENER);

        taskListeners.add(taskCreateListener);
        taskListeners.add(taskDeleteListener);
        return taskListeners;
    }

    /**
     *  封装默认任务监听器
     * @return 任务监听器列表
     */
    private List<FlowableListener> signTaskListeners() {
        List<FlowableListener> taskListeners = new ArrayList<>();
        FlowableListener taskSignCreateListener = listenerService.generateListener(TaskListener.EVENTNAME_CREATE,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.TASK_SIGN_CREATE_LISTENER);

        FlowableListener taskDeleteListener = listenerService.generateListener(TaskListener.EVENTNAME_DELETE,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.TASK_DELETE_LISTENER);
        taskListeners.add(taskSignCreateListener);
        taskListeners.add(taskDeleteListener);
        return taskListeners;
    }

    /**
     * 封装默认自动任务监听器列表
     * @return list
     */
    private List<FlowableListener> defaultAutoTaskListeners() {
        List<FlowableListener> autoTaskListeners = new ArrayList<>();
        FlowableListener autoTaskListener = listenerService.generateListener(BaseExecutionListener.EVENTNAME_START,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.AUTO_TASK_LISTENER);
        autoTaskListeners.add(autoTaskListener);
        return autoTaskListeners;
    }

    /**
     * 内部子流程实例监听器
     * @return list
     */
    private List<FlowableListener> subProcessListeners() {
        List<FlowableListener> subProcessListeners = new ArrayList<>();
        FlowableListener subProcessStartListener = listenerService.generateListener(BaseExecutionListener.EVENTNAME_START,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.SUB_PROCESS_START_LISTENER);
        FlowableListener subProcessEndListener = listenerService.generateListener(BaseExecutionListener.EVENTNAME_END,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.SUB_PROCESS_END_LISTENER);
        subProcessListeners.add(subProcessStartListener);
        subProcessListeners.add(subProcessEndListener);
        return subProcessListeners;
    }

    /**
     * 外部子流程实例监听器
     * @return list
     */
    private List<FlowableListener> callActivityListeners() {
        List<FlowableListener> callActivityListeners = new ArrayList<>();
        FlowableListener callActivityStartListener = listenerService.generateListener(BaseExecutionListener.EVENTNAME_START,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.CALL_SUB_PROCESS_START_LISTENER);
        FlowableListener callActivityEndListener = listenerService.generateListener(BaseExecutionListener.EVENTNAME_END,
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION, ListenerService.CALL_SUB_PROCESS_END_LISTENER);
        callActivityListeners.add(callActivityStartListener);
        callActivityListeners.add(callActivityEndListener);
        return callActivityListeners;
    }

    /**
     * 将监听器和流程进行绑定
     * @param bpmnModel bpmn模型
     */
    private void addListenersToProcess(BpmnModel bpmnModel) {
        // 生成默认实例监听器
        List<FlowableListener> executionListeners = defaultExecutionListeners();
        // 生成默认用户任务监听器
        List<FlowableListener> taskListeners = defaultTaskListeners();
        // 生成默认自动任务监听器
        List<FlowableListener> autoTaskListeners = defaultAutoTaskListeners();
        // 生成会签任务监听器
        List<FlowableListener> signTaskListeners = signTaskListeners();
        // 生成内部子流程监听器
        List<FlowableListener> subProcessListeners = subProcessListeners();
        // 生成外部子流程监听器
        List<FlowableListener> callActivityListeners = callActivityListeners();

        // 获取所有流程
        List<Process> processes = bpmnModel.getProcesses();
        for (Process process : processes) {
            // 遍历所有流程，为每个流程添加默认实例监听器，如果已经有了则不必添加
            if (process.getExecutionListeners().size() < 1) {
                process.setExecutionListeners(executionListeners);
            }
            Collection<FlowElement> flowElements = process.getFlowElements();
            for (FlowElement element : flowElements) {
                // 遍历流程中的元素，如果是用户任务节点，添加默认任务监听器，已经添加的无需再次添加
                cycleAddListeners(taskListeners, autoTaskListeners, signTaskListeners, subProcessListeners, callActivityListeners, element);
            }
        }
    }

    private void cycleAddListeners(List<FlowableListener> taskListeners, List<FlowableListener> autoTaskListeners, List<FlowableListener> signTaskListeners,
                                   List<FlowableListener> subProcessListeners,List<FlowableListener> callActivityListeners,FlowElement element) {
        if (element instanceof UserTask) {
            if (((UserTask) element).getTaskListeners().size() < 1) {
                if (((UserTask) element).getLoopCharacteristics() != null) {
                    ((UserTask) element).setTaskListeners(signTaskListeners);
                }else{
                    ((UserTask) element).setTaskListeners(taskListeners);
                }
            }
        }
        // 如果是自动任务节点，添加自动任务监听器，已经添加的无需再次添加
        if (element instanceof ScriptTask || element instanceof SendTask || element instanceof ServiceTask) {
            if (element.getExecutionListeners().size() < 1) {
                element.setExecutionListeners(autoTaskListeners);
            }
        }

        // 如果是内嵌子流程
        if (element instanceof SubProcess) {
            element.setExecutionListeners(subProcessListeners);
            Collection<FlowElement> flowElements = ((SubProcess) element).getFlowElements();
            for (FlowElement elem : flowElements) {
                // 遍历流程中的元素，如果是用户任务节点，添加默认任务监听器，已经添加的无需再次添加
                cycleAddListeners(taskListeners, autoTaskListeners, signTaskListeners, subProcessListeners, callActivityListeners, elem);
            }
        }

        // 如果是外部子流程
        if (element instanceof CallActivity) {
            element.setExecutionListeners(callActivityListeners);
        }
    }

    /**
     * 部署流程模型
     * @param actModel 流程模型对象
     */
    @Transactional(rollbackFor = Exception.class)
    public Deployment deploy(ActDefModel actModel) throws Exception{
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        BpmnModel bpmnModel = getBpmnModel(actModel);

        Deployment deployment = deploymentBuilder.addBpmnModel(actModel.getName() + StringPool.SUFFIX_BPMN, bpmnModel)
                .name(actModel.getName()).key(actModel.getModelKey()).category(actModel.getTypeId()).deploy();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();

        // 修改模型状态为测试状态，并持久化到数据库
        actModel.setStatus(ActDefModel.STATUS_TEST);
        actModel.setProcDefId(processDefinition.getId());
        actModel.setProcDefKey(processDefinition.getKey());
        actModel.setDeployId(deployment.getId());
        actModel.setIsMain(ActDefModel.IS_MAIN);
        actDefModelDao.update(actModel);
        //保存节点
        saveOrUpdateNodeSet(actModel,true);
        return deployment;
    }

    /**
     * 获取bpmn模型
     * @param model 模型对象
     * @return bpmn模型
     */
    public BpmnModel getBpmnModel(ActDefModel model) {
        BpmnModel bpmnModel;
        try {
            ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(model.getModelEditorJson());
            bpmnModel =  bpmnJsonConverter.convertToBpmnModel(editorJsonNode);
        } catch (Exception e) {
            LOGGER.error("Could not generate BPMN 2.0 model for {}", model.getId(), e);
            throw new InternalServerErrorException("Could not generate BPMN 2.0 model");
        }

        return bpmnModel;
    }

    /**
     * 更新资源xml
     * @param model 流程模型
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateResource(ActDefModel model) throws Exception{
        Deployment deployment = repositoryService.createDeploymentQuery().deploymentKey(model.getModelKey()).latest().singleResult();
        String resourceName = model.getName() + StringPool.SUFFIX_BPMN;
        byte[] bytes = bpmnXmlService.getBpmnXML(getBpmnModel(model));
        ByteArrayEntityImpl byteArrayEntity = actGeByteArrayDao.getByteArrayEntityByNameAndDeploymentId(StringPool.PERCENT + StringPool.SUFFIX_BPMN,deployment.getId());

        if (byteArrayEntity == null) {
            throw new BadRequestException("无法找到资源");
        }
        byteArrayEntity.setBytes(bytes);
        byteArrayEntity.setName(resourceName);
        actGeByteArrayDao.updateByteArray(byteArrayEntity);
        springProcessEngineConfiguration.getProcessDefinitionCache().remove(model.getProcDefId());
        //更新节点
        saveOrUpdateNodeSet(model,false);

    }

    /**
     * 保存模型的参数设置
     * @param model 模型对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveParam(ActDefModel model){
        actDefModelDao.saveParam(model);
    }

    /**
     * 保存或更新节点
     * @param actDefModel 流程定义模型对象
     * @param isAdd 是否增加节点设置
     * @throws Exception 异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateNodeSet(ActDefModel actDefModel,boolean isAdd) throws Exception{
        //获取所有的用户节点和一级外部子流程节点
        List<FlowElement> flowElements = getFlowElements(actDefModel,true);
        if(isAdd){
            //增加节点
            for(FlowElement flowElement:flowElements){
                addNodeSet(actDefModel,flowElement);
            }
        }else{
            //修改节点
            delAndUpdNodeSet(actDefModel, flowElements);
        }
    }

    /**
     * 更新模型id
     * @param selectedIds 选中的模型id组合的字符串
     * @param typeId 分类id
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateModelType(String selectedIds, String typeId) {
        if (selectedIds.contains(StringPool.COMMA)) {
            String[] modelIds = selectedIds.split(StringPool.COMMA);
            Map<String, Object> params = new HashMap<>(2);
            for (String modelId : modelIds) {
                params.put("modelId", modelId);
                params.put("typeId", typeId);
                actDefModelDao.updateModelType(params);
            }
        }else {
            Map<String, Object> params = new HashMap<>(2);
            params.put("modelId", selectedIds);
            params.put("typeId", typeId);
            actDefModelDao.updateModelType(params);
        }
    }

    /**
     * 添加节点
     * @param actDefModel 流程定义模型
     * @param flowNode 节点
     * @throws Exception 异常
     */
    private void addNodeSet(ActDefModel actDefModel,FlowElement flowNode) throws Exception{
        if(flowNode instanceof CallActivity){
            //外部子流程
            String modelKey = ((CallActivity) flowNode).getCalledElement();
            //被调用的外部子流程
            ActDefModel calledActDefModel = actDefModelDao.getByModelKey(modelKey);
            //获取该外部子流程的所有的用户节点
            List<FlowElement> flowElements = getFlowElements(calledActDefModel,true);
            for(FlowElement flowElement : flowElements){
                addNodeSet(calledActDefModel, flowElement, actDefModel.getProcDefId());
            }
        }else{
            //用户节点
            addNodeSet(actDefModel, flowNode, "");
        }
    }

    /**
     * 保存节点
     * @param actDefModel 流程模型
     * @param flowNode 节点
     * @param parentProcDefId 父流程id
     * @throws Exception 异常
     */
    private void addNodeSet(ActDefModel actDefModel,FlowElement flowNode, String parentProcDefId) throws Exception{
        if(!(flowNode instanceof CallActivity)){
            String procDefId=actDefModel.getProcDefId();
            Integer nodeOrder = 0;
            BpmNodeSet bpmNodeSet=new BpmNodeSet();
            bpmNodeSet.setSetId(UUIDUtils.getUUIDFor32());
            bpmNodeSet.setFormType((short)-1);
            bpmNodeSet.setProcDefId(procDefId);
            bpmNodeSet.setNodeId(flowNode.getId());
            bpmNodeSet.setNodeName(flowNode.getName());
            bpmNodeSet.setNodeOrder(nodeOrder);
            if(StringUtil.isNotEmpty(parentProcDefId)){
                bpmNodeSet.setParentProcDefId(parentProcDefId);
            }
            bpmNodeSetDao.add(bpmNodeSet);
        }
    }

    /**
     * 更新节点
     * @param actDefModel 新的模型
     * @param flowElements 所有的用户节点和外部子流程节点
     * @throws Exception 异常
     */
    private void delAndUpdNodeSet(ActDefModel actDefModel, List<FlowElement> flowElements) throws Exception{
        //获取原来的所有的用户节点
        Map<String,BpmNodeSet> nodeSetMap = bpmNodeSetService.getMapByProcDefId(actDefModel.getProcDefId());
        //获取原来的所有外部子流程节点
        List<BpmNodeSet> callActiviti = bpmNodeSetService.queryByParentProcDefId(actDefModel.getProcDefId());
        //删除无用的节点
        delNodeSet(nodeSetMap, callActiviti, flowElements);
        //添加新增的节点
        updNodeSet(actDefModel, nodeSetMap, callActiviti, flowElements);
    }

    /**
     * 删除无用的节点
     * @param oldSetMap 旧的用户节点
     * @param callActiviti 旧的外部子流程节点
     * @param flowNodes 新的所有用户节点和外部子流程节点
     */
    private void delNodeSet(Map<String,BpmNodeSet> oldSetMap, List<BpmNodeSet> callActiviti, Collection<FlowElement> flowNodes){
        if(callActiviti!=null){
            //删除子流程节点数据
            for(BpmNodeSet nodeSet : callActiviti){
                String procDefId=nodeSet.getProcDefId();
                String callDefKey = procDefId.split(":")[0];
                boolean inflag=false;
                for(FlowElement flowNode:flowNodes){
                    if(flowNode instanceof CallActivity){
                        String defKey = ((CallActivity) flowNode).getCalledElement();
                        if(defKey.equals(callDefKey)){
                            inflag=true;
                            break;
                        }
                    }
                }
                if(inflag){
                    continue;
                }
                bpmNodeSetService.delByProcDefIdAndParentProcDefId(nodeSet.getProcDefId(), nodeSet.getParentProcDefId());
            }
        }

        Iterator<String> keys=oldSetMap.keySet().iterator();
        while(keys.hasNext()){
            String nodeId=keys.next();
            boolean inflag=false;
            for(FlowElement flowNode:flowNodes){
                if(flowNode.getId().equals(nodeId)){
                    inflag=true;
                    break;
                }
            }
            if(inflag){
                continue;
            }
            BpmNodeSet bpmNodeSet=oldSetMap.get(nodeId);
            //删除本节点和做为内部子流程的节点数据
            bpmNodeSetService.delByProcDefIdNodeId(bpmNodeSet.getNodeId(), bpmNodeSet.getProcDefId());
        }
    }

    /**
     * 更新节点
     * @param actDefModel 新模型
     * @param oldSetMap 旧的用户节点
     * @param callActiviti 旧的外部子流程节点
     * @param flowNodes 所有用户节点和外部子流程节点
     * @throws Exception 异常
     */
    private void updNodeSet(ActDefModel actDefModel,Map<String,BpmNodeSet> oldSetMap, List<BpmNodeSet> callActiviti, Collection<FlowElement> flowNodes) throws Exception{
        for(FlowElement flowNode:flowNodes){
            if(flowNode instanceof CallActivity){
                //若为新添加的外部子流程节点，则添加子流程的节点数据
                String defKey = ((CallActivity) flowNode).getCalledElement();
                boolean inflag=false;
                if(callActiviti!=null){
                    for(BpmNodeSet nodeSet : callActiviti){
                        String procDefId=nodeSet.getProcDefId();
                        String[] defKeys = procDefId.split(":");
                        if(defKey.equals(defKeys[0])){
                            inflag=true;
                            break;
                        }
                    }
                }
                if(inflag){
                    continue;
                }
                ActDefModel calledActDefModel = actDefModelDao.getByModelKey(defKey);
                Collection<FlowElement> flowElements = getFlowElements(calledActDefModel,true);
                for(FlowElement flowElement : flowElements){
                    addNodeSet(calledActDefModel, flowElement, actDefModel.getProcDefId());
                }
            }else{
                //用户节点
                if(BeanUtils.isNotEmpty(oldSetMap) && oldSetMap.containsKey(flowNode.getId())){
                    Integer nodeOrder = 0;
                    BpmNodeSet bpmNodeSet=oldSetMap.get(flowNode.getId());
                    bpmNodeSet.setNodeName(flowNode.getName());
                    bpmNodeSet.setNodeOrder(nodeOrder);
                    bpmNodeSetService.update(bpmNodeSet);
                    String procDefId=actDefModel.getProcDefId();
                    //当该流程作为外部子流程时，同步更新父流程中的节点设置
                    List<BpmNodeSet> list = bpmNodeSetService.queryParentByProcDefIdAndNodeId(flowNode.getId(),procDefId);
                    updateParentNodeSet(list, flowNode);
                }else{
                    addNodeSet(actDefModel, flowNode,"");
                    addParentNodeSet(actDefModel, flowNode);
                }
            }
        }
    }

    /**
     * 更新父流程关于该节点的设置
     * @param nodeSetList 所有关于该节点的设置
     * @param flowNode 新的节点
     */
    private void updateParentNodeSet(List<BpmNodeSet> nodeSetList, FlowElement flowNode){
        if(BeanUtils.isNotEmpty(nodeSetList)){
            for(BpmNodeSet bpmNodeSet : nodeSetList){
                Integer nodeOrder = 0;
                bpmNodeSet.setNodeName(flowNode.getName());
                bpmNodeSet.setNodeOrder(nodeOrder);
                bpmNodeSetDao.update(bpmNodeSet);
            }
        }
    }

    /**
     * 给父流程中添加关于本节点的节点设置
     * @param actDefModel 流程模型
     * @param flowNode 该节点
     * @throws Exception 异常
     */
    private void addParentNodeSet(ActDefModel actDefModel, FlowElement flowNode) throws Exception {
        String procDefId = actDefModel.getProcDefId();
        List<BpmNodeSet> list = bpmNodeSetService.queryParentIdByProcDefId(procDefId);
        if (BeanUtils.isNotEmpty(list)) {
            for (BpmNodeSet nodeSet : list) {
                if (StringUtil.isNotEmpty(nodeSet.getParentProcDefId())) {
                    Integer nodeOrder = 0;
                    BpmNodeSet bpmNodeSet = new BpmNodeSet();
                    bpmNodeSet.setSetId(UUIDUtils.getUUIDFor32());
                    bpmNodeSet.setFormType((short) -1);
                    bpmNodeSet.setProcDefId(procDefId);
                    bpmNodeSet.setNodeId(flowNode.getId());
                    bpmNodeSet.setNodeName(flowNode.getName());
                    bpmNodeSet.setNodeOrder(nodeOrder);
                    bpmNodeSet.setParentProcDefId(nodeSet.getParentProcDefId());
                    bpmNodeSetDao.add(bpmNodeSet);
                }
            }
        }
    }


    /**
     * 获取所有的用户节点、内部子流程中的用户节点、外部子流程节点
     * @param actDefModel 流程定义模型
     * @return 流程元素列表
     * @throws Exception 异常
     */
    private List<FlowElement> getFlowElements(ActDefModel actDefModel,Boolean deepIntoSub) throws Exception{
        BpmnModel bpmnModel = getBpmnModel(actDefModel);
        Class<FlowElement>[] classes= new Class[]{
                UserTask.class,
                CallActivity.class
        };
        return BPMN20Util.getFlowElementByType(bpmnModel.getMainProcess(),deepIntoSub,classes);
    }

    /**
     * 获取分支条件数据
     * @param modelId 模型id
     * @param nodeId 节点id
     * @throws Exception 异常
     */
    public Map<String, Object> getConditionData(String modelId, String nodeId) throws Exception{
        Map<String, Object> attributeMap = new HashMap<>();
        ActDefModel actDefModel = this.getOneById(modelId);
        String procDefId = actDefModel.getProcDefId();
        //节点map
        Map<String, FlowNodeInfo> nodeMap = NodeCache.getByProcDefId(procDefId);
        //当前节点
        FlowNodeInfo currentNode = nodeMap.get(nodeId);
        String currentNodeType = currentNode.getNodeType();
        Boolean ifInclusiveGateway = FlowNodeInfo.TYPE_INCLUSIVEGATEWAY.equals(currentNodeType);
        attributeMap.put("ifInclusiveGateway", ifInclusiveGateway);
        //条件同步网关
        if(ifInclusiveGateway){
            Object canChoicePathNodeId = null;
            Map canChoicePathNodeMap = actDefModel.getCanChoicePathNodeMap();
            if (BeanUtils.isNotEmpty(canChoicePathNodeMap)) {
                canChoicePathNodeId = canChoicePathNodeMap.get(currentNode.getNodeId());
            }
            if (canChoicePathNodeId != null) {
                attributeMap.put("canChoicePathGateway", currentNode.getNodeId());
                attributeMap.put("selectCanChoicePathNodeId", canChoicePathNodeId);
            }
        }
        FlowNodeInfo flowNodeInfo;
        // 找到该节点的入口节点及出口节点
        List<FlowNodeInfo> incomeNodes = new ArrayList<>();
        for(FlowNodeInfo nodeInfo:currentNode.getPreFlowNodesInfo()){
            flowNodeInfo = new FlowNodeInfo(nodeInfo.getNodeId(),nodeInfo.getNodeName(),nodeInfo.getNodeType(),nodeInfo.getIsMultiInstance());
            incomeNodes.add(flowNodeInfo);
        }
        attributeMap.put("incomeNodes", incomeNodes);

        String deployId = actDefModel.getDeployId();
        String name = actDefModel.getName()+StringPool.SUFFIX_BPMN;
        ByteArrayEntityImpl byteArrayEntity = actGeByteArrayDao.getByteArrayEntityByNameAndDeploymentId(name,deployId);
        String xml =  new String(byteArrayEntity.getBytes(), StandardCharsets.UTF_8);
        Map<String, String> conditionMap = BpmUtil.getDecisionConditions(xml,nodeId);
        List<FlowNodeInfo> outcomeNodes = new ArrayList<>();
        for(FlowNodeInfo nodeInfo:currentNode.getNextFlowNodesInfo()){
            flowNodeInfo = new FlowNodeInfo(nodeInfo.getNodeId(),nodeInfo.getNodeName(),nodeInfo.getNodeType(),nodeInfo.getIsMultiInstance());
            String condition = conditionMap.get(nodeInfo.getNodeId());
            if (BeanUtils.isNotEmpty(condition)) {
                flowNodeInfo.setCondition(condition);
            }
            outcomeNodes.add(flowNodeInfo);
        }
        attributeMap.put("outcomeNodes",outcomeNodes);
        attributeMap.put("modelId",modelId);
        attributeMap.put("nodeId",nodeId);
        attributeMap.put("deployId",deployId);
        return attributeMap;
    }

    /**
     * 根据流程定义id获取定义模型实体
     * @param procDefId 流程定义id
     * @return 模型实体数据
     */
    public ActDefModel getByProcDefId(String procDefId) {
        return actDefModelDao.getByProcDefId(procDefId);
    }

    /**
     * 发布新版时，根据模型定义key将其他版本设为非主版本
     * @param modelKey 模型Key
     * @param parentModelId 主版本id
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateSubVersions(String modelKey,String parentModelId){
        Map<String, Object> params = new HashMap<>(2);
        params.put("parentModelId",parentModelId);
        params.put("modelKey",modelKey);
        actDefModelDao.updateSubVersions(params);
    }

    /**
     * 获取某个流程的历史版本
     * @param map 查询条件
     * @return list
     */
    public List<ActDefModel> selectAllHistoryVersions(Map map) {
        return actDefModelDao.queryModelByParentModelId(map);
    }


    /**
     * 批量删除流程定义
     * 2019-12-16 jyq新增
     * @param aryId 流程id数组
     * @param isOnlyVersion 是否只删除历史版本
     */
    @Transactional(rollbackFor = Exception.class)
    public void delModelByIdArray(String[] aryId,boolean isOnlyVersion){
        for (String modelId: aryId) {
            delDefByModelId(modelId,isOnlyVersion);
        }
    }

    /**
     * 删除流程定义
     * 2019-12-16 jyq修改方法名称
     * @param modelId 模型id
     * @param isOnlyVersion 是否仅删除该版本
     */
    @Transactional(rollbackFor = Exception.class)
    public void delDefByModelId(String modelId, boolean isOnlyVersion) {
        if (BeanUtils.isEmpty(modelId)) { return; }

        ActDefModel actDefModel = actDefModelDao.getById(modelId);
        //版本未发布
        if(actDefModel.getDeployId()==null){
            delById(actDefModel.getId());
            return ;
        }

        //是否仅删除该版本
        if(isOnlyVersion){
            delActDefModel(actDefModel);
            return ;
        }

        String procFlowKey = actDefModel.getProcDefKey();
        List<ActDefModel> list = actDefModelDao.queryAllByProcDefKey(procFlowKey);

        //级联删除流程系统表
        for(ActDefModel defModel:list){
            delActDefModel(defModel);
        }
        //删除分管授权的流程权限表内容  BPM_DEF_AUTH_ACT
        bpmDefAuthorizeActDao.delByModelKey(actDefModel.getModelKey());
    }

    /**
     * 删除模型及级联数据
     * @param actDefModel  流程定义模型对象
     */
    private void delActDefModel(ActDefModel actDefModel) {
        String deployId = actDefModel.getDeployId();
        String modelId = actDefModel.getId();
        String procDefId = actDefModel.getProcDefId();
        if (StringUtil.isNotEmpty(procDefId)) {
            //删除流程运行实例表单数据  BPM_FORM_RUN
            bpmFormRunDao.delByProcDefId(procDefId);

            //删除流程节点操作按钮    BPM_NODE_BTN
            bpmNodeButtonDao.delByProcDefId(procDefId);
            //删除节点消息    BPM_NODE_MESSAGE
            bpmNodeMessageDao.delByProcDefId(procDefId);

            //删除节点特权    BPM_NODE_PRIVILEGE
            bpmNodePrivilegeDao.delByProcDefId(procDefId);

            //删除节点规则    BPM_NODE_RULE
            bpmNodeRuleDao.delByProcDefId(procDefId);

            //删除节点运行脚本  BPM_NODE_SCRIPT
            bpmNodeScriptDao.delByProcDefId(procDefId);

            //TODO 删除功能待补完
            //关联    BPM_NODE_WEBSERVICE 删除  BPM_NODE_WS_PARAMS
            /*List<BpmNodeWebService> bpmNodeWebServiceList =  bpmNodeWebServiceDao.getByProcDefId(procDefId);
            for(BpmNodeWebService bpmNodeWebService:bpmNodeWebServiceList){
                bpmNodeWsParamsDao.delByWebserviceId(bpmNodeWebService.getId());
            }
            删除webservice节点设置BPM_NODE_WEBSERVICE
            BpmNodeWebServiceDao.delByProcDefId(procDefId);*/

            //删除流程节点状态  BPM_PRO_STATUS
            bpmProStatusDao.delByProcDefId(procDefId);

            //删除定义催办信息BPM_TASK_DUE
            taskReminderDao.delByProcDefId(procDefId);

            //删除流程任务分发汇总    BPM_TASK_FORK
            taskForkService.delByProcDefId(procDefId);

            //删除流程运行实例 BPM_PRO_RUN,
            // 同时删除流程实例扩展 BPM_PRO_RUN_HIS、流程任务候选人  ACT_RU_IDENTITYLINK、// 流程任务 ACT_RU_TASK、流程变量  ACT_RU_VARIABLE、
            // 流程执行堆栈树  ACT_RU_EXECUTION、抄送转发  BPM_PRO_COPYTO、代理转办任务 BPM_TASK_EXE、通知任务接收人  BPM_COMMU_RECEIVER、任务是否已读 BPM_TASK_READ
            processRunService.delByProcDefId(procDefId);
            //删除流程意见信息  BPM_TASK_OPINION
            taskOpinionDao.delByProcDefId(procDefId);

            //删除任务提醒状态数据BPM_TASK_REMINDERSTATE

            //关联BPM_USER_CONDITION删除BPM_NODE_USER
            List<BpmUserCondition> bpmUserConditionList = bpmUserConditionDao.queryByProcDefIdForDel(procDefId);
            for (BpmUserCondition bpmUserCondition : bpmUserConditionList) {
                bpmNodeUserDao.delByConditionId(bpmUserCondition.getId());
            }
            //删除节点人员规则BPM_USER_CONDITION
            bpmUserConditionDao.delByProcDefId(procDefId);

            //删除流程执行堆栈    BPM_EXE_STACK
            executionStackDao.delByProcDefId(procDefId);

            //删除BPM_TKSIGN_DATA
            taskSignDataDao.delByProcDefId(procDefId);

            //删除BPM_NODE_SIGN会签规则
            bpmNodeSignDao.delByProcDefId(procDefId);

            // todo 删除流程引用相关代码
            //删除流程引用  refer_act_def_model
//            referActDefModelDao.delByModelId(modelId);

            //删除子表数据权限  BPM_SUBTABLE_RIGHTS
//            subTableRightsDao.delByProcDefId(procDefId);

            //删除表单数据权限  bpm_form_rights
            formRightsDao.delByProcDefId(procDefId);

            if(deployId!=null){

                //删除流程定义数据表ACT_GE_BYTEARRAY，ACT_RE_DEPLOYMENT，ACT_RE_PROCDEF
                actDefModelDao.delActRuTaskDeployId(procDefId);
                actDefModelDao.delActRuExecution(procDefId);
                actDefModelDao.delProcDefByDeployId(deployId);
            }

            //删除bpm_def_vars流程变量定义
            bpmDefVarDao.delByDefId(modelId);
            //删除流程(包括直接子流程)的节点数据BPM_NODE_SET
            bpmNodeSetDao.delByProcDefId(procDefId);

            actDefModelDao.delById(modelId);
        }
    }

    /**
     * 判断是否可以直接启动
     * @param modelId 流程模型Id
     * @return boolean
     */
    public boolean getCanDirectStart(String modelId){
        ActDefModel model = actDefModelDao.getById(modelId);
        Integer directStart = model.getDirectstart();
        if (null == directStart){
            return true;
        }
        return directStart.intValue() == 1;
    }

    /**
     * 根据流程定义key获取最新版本的模型
     * @param defKey 流程定义key
     * @return 流程模型对象
     */
    public ActDefModel getMainByDefKey(String defKey) {
        return actDefModelDao.getByModelKey(defKey);
    }

    /**
     * 获取某个流程的所有任务节点（除nodeId节点）
     * @param modelId 模型id
     * @param nodeId 节点id
     * @return map
     */
    public Map<String, String> getTaskNodes(String modelId, String nodeId) {
        ActDefModel actDefModel = actDefModelDao.getById(modelId);
        BpmnModel bpmnModel = getBpmnModel(actDefModel);
        Map<String, String> userNodeMap = bpmService.getTaskNodes(bpmnModel,nodeId);
        return userNodeMap;
    }



    /**
     * 根据流程定义获取表单结果
     * @param procDefId 流程定义id
     * @param parentProcDefId 父流程定义id
     * @return BpmFormResult
     */
    public BpmFormResult getBpmFormResult(String procDefId, String parentProcDefId) {
        List<FormTable> list =formTableDao.queryTableNameByProcDefIdOrParentProcDefId(procDefId,parentProcDefId);
        BpmFormResult bpmFormResult = new BpmFormResult();
        //没有找到对应的表单
        if(list.isEmpty()){
            bpmFormResult.setResult(2);
        }
        else if(list.size()>1){
            bpmFormResult.setResult(1);
        }
        else{
            FormTable formTable=list.get(0);
            String tableName=formTable.getTableName();
            String dsName=formTable.getDsAlias();
            Integer isexternal=formTable.getIsExternal();
            String name=tableName;
            if(isexternal==1){
                name=dsName +"_" + tableName;
            }
            bpmFormResult.setTableName(name);
        }

        return bpmFormResult;
    }

    /**
     * 保存及更新流程定义的相关配置
     * @param newModelId 新模型id
     * @param oldModelId 旧模型id
     */
    private void saveOrUpdateSetting(String newModelId,String oldModelId){

        if(StringUtil.isEmpty(oldModelId)){
            return;
        }

        ActDefModel newModel =getOneById(newModelId);
        ActDefModel oldModel =getOneById(oldModelId);
        BpmnModel bpmnModel = getBpmnModel(newModel);

        String newProcDefId=newModel.getProcDefId();
        String oldProcDefId=oldModel.getProcDefId();
        if(StringUtil.isEmpty(oldProcDefId)){
            return;
        }

        //同步流程起始表单和默认表单配置。
        List<BpmNodeSet> list=bpmNodeSetDao.queryOtherSetByProcDefId(oldProcDefId);
        for(BpmNodeSet nodeSet:list){
            nodeSet.setSetId(UUIDUtils.getUUIDFor32());
            nodeSet.setProcDefId(newProcDefId);
            bpmNodeSetDao.add(nodeSet);
        }

        // 同步起始表单按钮
        List<BpmNodeButton> startBtnList = bpmNodeButtonService.getByStartForm(oldProcDefId);
        syncNodeButton(newModelId, newProcDefId, startBtnList);

        //BPM_DEF_VARS	流程变量定义 OK
        List<BpmDefVar> defVarList=bpmDefVarDao.queryByModelId(oldModelId);
        if(BeanUtils.isNotEmpty(defVarList)){
            for(BpmDefVar oldVar:defVarList){
                BpmDefVar newVar=(BpmDefVar)oldVar;
                newVar.setVarId(UUIDUtils.getUUIDFor32());
                newVar.setModelId(newModelId);
                bpmDefVarDao.add(newVar);
            }
        }
        //BPM_NODE_SCRIPT	流程开始结束节点事件脚本
        List<BpmNodeScript> nodeScripts= bpmNodeScriptDao.queryByProcDefId(oldProcDefId);
        Class<FlowElement>[] classes= new Class[]{
                StartEvent.class,
                EndEvent.class
        };
        List<FlowElement> eventFlowElements = BPMN20Util.getFlowElementByType(bpmnModel.getMainProcess(),true,classes);
        for (FlowElement eventFlow:eventFlowElements) {
            String nodeId=eventFlow.getId();
            for(BpmNodeScript script:nodeScripts){
                if(script.getNodeId().equals(nodeId)){
                    BpmNodeScript newScript=script;
                    newScript.setId(UUIDUtils.getUUIDFor32());
                    newScript.setProcDefId(newProcDefId);
                    bpmNodeScriptDao.add(newScript);
                }
            }
        }

        //BPM_NODE_SET	流程节点配置
        List<BpmNodeSet> newNodeSetList= bpmNodeSetDao.queryByProcDefId(newProcDefId);
        List<BpmNodeSet> oldNodeSetList= bpmNodeSetDao.queryByProcDefId(oldProcDefId);
        Map<String, BpmNodeSet> oldNodeSetMap=new HashMap<>();
        for(BpmNodeSet bpmNodeSet:oldNodeSetList){
            oldNodeSetMap.put(bpmNodeSet.getNodeId(), bpmNodeSet);
        }
        if(BeanUtils.isEmpty(newNodeSetList) || BeanUtils.isEmpty(oldNodeSetMap)){
            return ;
        }
        for(BpmNodeSet bpmNodeSet:newNodeSetList){
            String nodeId=bpmNodeSet.getNodeId();
            if(!oldNodeSetMap.containsKey(nodeId)){
                continue;
            }

            BpmNodeSet oldBpmNodeSet=oldNodeSetMap.get(nodeId);
            String oldSetId=oldBpmNodeSet.getSetId();

            //更新当前的节点配置信息
            bpmNodeSet.setAfterHandler(oldBpmNodeSet.getAfterHandler());
            bpmNodeSet.setBeforeHandler(oldBpmNodeSet.getBeforeHandler());
            bpmNodeSet.setFormDefId(oldBpmNodeSet.getFormDefId());
            bpmNodeSet.setFormDefName(oldBpmNodeSet.getFormDefName());
            bpmNodeSet.setFormKey(oldBpmNodeSet.getFormKey());
            bpmNodeSet.setFormType(oldBpmNodeSet.getFormType());
            bpmNodeSet.setFormUrl(oldBpmNodeSet.getFormUrl());
            bpmNodeSet.setDetailUrl(oldBpmNodeSet.getDetailUrl());
            bpmNodeSet.setIsHideOption(oldBpmNodeSet.getIsHideOption());
            bpmNodeSet.setIsHidePath(oldBpmNodeSet.getIsHidePath());
            bpmNodeSet.setIsJumpForDef(oldBpmNodeSet.getIsJumpForDef());
            bpmNodeSet.setJoinTaskKey(oldBpmNodeSet.getJoinTaskKey());
            bpmNodeSet.setJoinTaskName(oldBpmNodeSet.getJoinTaskName());
            bpmNodeSet.setNodeType(oldBpmNodeSet.getNodeType());
            bpmNodeSet.setInformType(oldBpmNodeSet.getInformType());
            bpmNodeSet.setJumpType(oldBpmNodeSet.getJumpType());
            bpmNodeSet.setOldFormKey(oldBpmNodeSet.getOldFormKey());
            bpmNodeSetDao.update(bpmNodeSet);


            //BPM_NODE_RULE	流程节点规则
            List<BpmNodeRule> nodeRuleList=bpmNodeRuleDao.getByProcDefIdNodeId(oldProcDefId, nodeId);
            if(BeanUtils.isNotEmpty(nodeRuleList)){
                for(BpmNodeRule oldRule:nodeRuleList){
                    BpmNodeRule newRule=(BpmNodeRule)oldRule;
                    newRule.setRuleId(UUIDUtils.getUUIDFor32());
                    newRule.setProcDefId(newProcDefId);
                    bpmNodeRuleDao.add(newRule);
                }
            }

            //BPM_NODE_SCRIPT	流程节点事件脚本
            List<BpmNodeScript> nodeScriptList= bpmNodeScriptDao.queryBpmNodeScript(nodeId,oldProcDefId);
            if(BeanUtils.isNotEmpty(nodeScriptList)){
                for(BpmNodeScript oldScript:nodeScriptList){
                    BpmNodeScript newScript=(BpmNodeScript)oldScript;
                    newScript.setId(UUIDUtils.getUUIDFor32());
                    newScript.setProcDefId(newProcDefId);
                    bpmNodeScriptDao.add(newScript);
                }
            }

            //BPM_USER_CONDITION 流程节点人员规则
            List<BpmUserCondition> userConditionList = bpmUserConditionDao.queryBySetId(oldSetId);
            if(BeanUtils.isNotEmpty(userConditionList)){
                for(BpmUserCondition oldCondition:userConditionList){
                    BpmUserCondition newCondition= (BpmUserCondition) oldCondition.clone();
                    newCondition.setId(UUIDUtils.getUUIDFor32());
                    newCondition.setProcDefId(newProcDefId);
                    newCondition.setSetId(bpmNodeSet.getSetId());
                    bpmUserConditionDao.add(newCondition);
                    //BPM_NODE_USER 	流程节点人员
                    List<BpmNodeUser> nodeUserList = bpmNodeUserDao.getByConditionId(oldCondition.getId());
                    if(BeanUtils.isNotEmpty(nodeUserList)){
                        for(BpmNodeUser oldUser:nodeUserList){
                            BpmNodeUser newUser= oldUser;
                            newUser.setNodeUserId(UUIDUtils.getUUIDFor32());
                            newUser.setConditionId(newCondition.getId());
                            bpmNodeUserDao.add(newUser);
                        }
                    }
                }
            }

            // BPM_NODE_MESSAGE	流程消息节点
            List<BpmNodeMessage> nodeMessageList=bpmNodeMessageDao.queryByProcDefId(oldProcDefId);
            if(BeanUtils.isNotEmpty(nodeMessageList)){
                for(BpmNodeMessage oldMessage : nodeMessageList){
                    BpmNodeMessage newMessage=(BpmNodeMessage)oldMessage.clone();
                    newMessage.setId(UUIDUtils.getUUIDFor32());
                    newMessage.setProcDefId(newProcDefId);
                    bpmNodeMessageDao.add(newMessage);
                }
            }

            // BPM_NODE_SIGN 任务会签设置
            BpmNodeSign nodeSign= bpmNodeSignDao.getByProcDefIdAndNodeId(oldProcDefId,nodeId);
            if(BeanUtils.isNotEmpty(nodeSign)){
                BpmNodeSign newSign=(BpmNodeSign)nodeSign.clone();
                newSign.setSignId(UUIDUtils.getUUIDFor32());
                newSign.setProcDefId(newProcDefId);
                bpmNodeSignDao.add(newSign);
            }

            // BPM_NODE_BTN 操作按钮节点设置
            List<BpmNodeButton> nodeButtonList = bpmNodeButtonService.getByDefNodeId(oldProcDefId, nodeId);
            syncNodeButton(newModelId, newProcDefId, nodeButtonList);

            // BPM_TASK_DUE 催办
            List<TaskReminder> taskReminders = taskReminderDao.queryByProcDefAndNodeId(oldProcDefId, nodeId);
            for(TaskReminder taskReminder:taskReminders){
                taskReminder.setProcDefId(newProcDefId);
                taskReminder.setTaskDueId(UUIDUtils.getUUIDFor32());
                taskReminderDao.add(taskReminder);
            }
        }

    }

    /**
     * 同步新旧版本按钮
     * @param newModelId 新模型id
     * @param newProcDefId 新flowable流程定义id
     * @param buttonList 按钮list
     */
    private void syncNodeButton(String newModelId, String newProcDefId, List<BpmNodeButton> buttonList) {
        if (!buttonList.isEmpty()) {
            for(BpmNodeButton oldButton:buttonList){
                BpmNodeButton newBtn=oldButton;
                newBtn.setId(UUIDUtils.getUUIDFor32());
                newBtn.setProcDefId(newProcDefId);
                newBtn.setModelId(newModelId);
                bpmNodeButtonDao.add(newBtn);
            }
        }
    }

    /**
     * 根据条件查询定义的流程
     * @param queryFilter 查询条件
     */
    public List<ActDefModel> queryAuthorizedList(QueryFilter queryFilter){
        queryFilter.addFilter("validStatus","1");
        // 根据租户Id过滤
        queryFilter.addFilter("tenantId",sysOrgService.getSuperTenantIdByOrgId(ContextUtil.getCurrentOrgId()));
        // 根据流程分管授权过滤
        String userId = ContextUtil.getCurrentUserId();
        if(StringUtil.isNotEmpty(userId)){
            Map<String,Object> actRightMap = bpmDefAuthorizeService.getActRightsByUserMap(userId,
                    BpmDefAuthorizeType.BPMDEFAUTHORIZE_RIGHT_TYPE.START,false,false);
            queryFilter.addFilter("actRights",actRightMap.get("authorizeIds"));
            queryFilter.addFilter("isNeedRight","yes");
        }
        return actDefModelDao.queryAuthorizedList(queryFilter);
    }
    /**
     * 分页查询新建流程列表
     * @param queryFilter 条件
     * @return list
     */
    public List<ActDefModel> queryNewProcessList(QueryFilter queryFilter){
        return actDefModelDao.queryNewProcessList(queryFilter);
    }

    /**
     * 清除数据 列表按钮
     * @param modelId 模型id
     */
    @Transactional(rollbackFor = Exception.class)
    public void cleanData(String modelId) throws Exception {
        ActDefModel actDefModel=actDefModelDao.getById(modelId);
        String procDefId = actDefModel.getProcDefId();
        //清除子数据
        cleanSubData(procDefId);
        //获取测试状态流程实例
        List<ProcessRun> processRunList = processRunService.queryTestRunByProcDefId(procDefId);
        for(ProcessRun run:processRunList){
            String runId = run.getRunId();
            String businessKey = run.getBusinessKey();
            String dsAlias = run.getDsAlias();
            String tableName = run.getTableName();
            //删除业务数据
            if(StringUtil.isNotEmpty(tableName)){
                if(StringUtil.isEmpty(dsAlias)||dsAlias.equals(DataSourceUtil.DEFAULT_DATASOURCE)){
                    tableName=tableName.replaceFirst(TableModel.CUSTOMER_TABLE_PREFIX, "");
                    FormTable bpmFormTable= formTableService.getByTableName(tableName);
                    formHandlerService.delById(businessKey, bpmFormTable);
                }else{
                    formHandlerService.delByDsAliasAndTableName(dsAlias,tableName,businessKey);
                }
            }
            //非草稿状态 清除act流程数据
            if(!ProcessRun.STATUS_FORM.equals(run.getStatus())){
                String procInstId = run.getProcInstId();
                if(!ProcessRun.STATUS_FINISH.equals(run.getStatus())){
                    executionDao.delVariableByProcInstId(procInstId);
                    taskDao.delCandidateByInstanceId(procInstId);
                    taskDao.delByInstanceId(procInstId);
                    executionDao.delExecutionByProcInstId(procInstId);
                }
                //删除节点状态
                bpmProStatusDao.delByProcInstId(procInstId);
                //删除堆栈信息
                executionStackDao.delByProcDefId(run.getProcDefId());
                //删除审批意见
                taskOpinionDao.delByProcInstId(procInstId);
                //任务已读信息
                taskReadService.delByProcInstId(procInstId);
            }
            //删除流程操作日志
            bpmRunLogService.delByRunId(runId);
            //删除抄送转发事宜
            processCopyToService.delByRunId(runId);
            //代理转办数据Bpm_task_exe删除 Bpm_commu_Receiver 通知接收人，BPM_TASK_READ 任务是否已读
            List<BpmTaskExe> bpmTaskExeList = bpmTaskExeService.queryByRunId(runId);
            if(BeanUtils.isNotEmpty(bpmTaskExeList)){
                for(BpmTaskExe bpmTaskExe:bpmTaskExeList){
                    commuReceiverService.delByTaskId(bpmTaskExe.getTaskId());
                }
                //删除转办代理事宜
                bpmTaskExeService.delByRunId(runId);
            }
            //删除流程实例
            processRunService.delById(runId);
        }
    }

    public void cleanSubData(String procDefId) throws Exception {
        if(NodeCache.hasExternalSubprocess(procDefId)){
            Map<String,FlowNodeInfo> flowNodeMap = NodeCache.getByProcDefId(procDefId);
            Set<String> keySet = flowNodeMap.keySet();
            for(Iterator<String> it = keySet.iterator();it.hasNext();){
                FlowNodeInfo flowNodeInfo =flowNodeMap.get(it.next());
                if("callActivity".equals(flowNodeInfo.getNodeType())){
                    String flowKey = flowNodeInfo.getAttribute("subFlowKey");
                    ActDefModel subActDefModel = actDefModelDao.getMainByModelKey(flowKey);
                    cleanData(subActDefModel.getId());
                }
            }
        }
    }


    /**
     * 判断流程是否允许转办。
     *
     * @param procDefId flowable流程定义id
     * @return boolean
     */
    public boolean allowDivert(String procDefId) {
        ActDefModel actDefModel = actDefModelDao.getByProcDefId(procDefId);
        return actDefModel.getAllowDivert() == 1;
    }

    /**
     * 获取外部子流程的key
     * @param bpmnModel 模型
     * @return key
     */
    public String getCallActivityModelKey(BpmnModel bpmnModel, String nodeId) {
        Process mainProcess = bpmnModel.getMainProcess();
        for (FlowElement element : mainProcess.getFlowElements()) {
            if ((element instanceof CallActivity) && (element.getId().equals(nodeId))) {
                return ((CallActivity) element).getCalledElement();
            }
        }

        return "";
    }

    /**
     * 导出XML
     *
     * @param ids id
     * @param map map
     * @param filePath 文件路径
     * @return String
     */
    public String exportXml(String[] ids, Map<String, Boolean> map, String filePath) throws Exception {
        ActDefModelXmlList actDefModelXmlList = new ActDefModelXmlList();
        List<ActDefModelXml> list = new ArrayList<ActDefModelXml>();
        for(String id :ids){
            //流程定义
            ActDefModel actDefModel = actDefModelDao.getById(id);
            ActDefModelXml actDefModelXml = this.exportActDefModel(actDefModel, ActDefModel.MAIN, map, filePath,null);
            list.add(actDefModelXml);
        }
        actDefModelXmlList.setActDefModelXmlList(list);
        return XmlBeanUtil.marshall(actDefModelXmlList,ActDefModelXmlList.class);
    }

    /**
     * 导出流程定义
     *
     * @param actDefModel 模型定义
     * @param isMain 是否主版本
     * @param map map
     * @param filePath 文件路径
     * @param parentProcDefId 父流程id
     * @return ActDefModelXml
     */
    private ActDefModelXml exportActDefModel(ActDefModel actDefModel, Short isMain, Map<String, Boolean> map, String filePath,String parentProcDefId) {

        ActDefModelXml actDefModelXml = new ActDefModelXml();
        if (BeanUtils.isEmpty(actDefModel)) {   return actDefModelXml; }
        if (BeanUtils.isEmpty(map)){     return actDefModelXml; }


        actDefModel = parseActDefModel(actDefModel,true);

        String modelId = actDefModel.getId();
        String procDefId=actDefModel.getProcDefId();
        String deployId=actDefModel.getDeployId();
        String modelKey = actDefModel.getModelKey();

        //将发布状态改为测试状态输出
        if(ActDefModel.STATUS_ENABLED.equals(actDefModel.getStatus())){
            actDefModel.setStatus(ActDefModel.STATUS_TEST);
        }
        //流程定义
        actDefModelXml.setActDefModel(actDefModel);

        //设置流程定义 历史版本
        if(map.get("actDefModelHistory") && isMain.shortValue() == ActDefModel.MAIN.shortValue()){
            this.exportActDefModelHistory(modelId,actDefModelXml,map,filePath);
        }
        // 内（外）部子流程
        if(map.get("subActDefModel") && BeanUtils.isNotIncZeroEmpty(deployId) ){
            this.exportSubActDefModel(actDefModel,actDefModelXml,map,filePath,procDefId);
        }


        //  老平台未实现该功能但又有此功能的勾选，故新增该功能，已完成
        //  常用语设置
        if(map.get("taskApprovalItems")){
            List<TaskApprovalItems> taskApprovalItemsList = taskApprovalItemsService.queryByModelKey(modelKey);
            if (BeanUtils.isNotEmpty(taskApprovalItemsList)) {
                actDefModelXml.setTaskApprovalItemsList(taskApprovalItemsList);
            }
        }

        // 流程跳转规则
        if (map.get("bpmNodeRule") && BeanUtils.isNotEmpty(procDefId)) {
            List<BpmNodeRule> ruleList = bpmNodeRuleDao.queryByProcDefId(procDefId);
            List<BpmNodeRule> ruleArrayList= new ArrayList<BpmNodeRule>(ruleList.size());
            for(BpmNodeRule rule : ruleList){
                rule.setConditionCode(parseScript(rule.getConditionCode(),true));
                ruleArrayList.add(rule);
            }
            actDefModelXml.setBpmNodeRuleList(ruleArrayList);
        }
        // 流程事件脚本
        if (map.get("bpmNodeScript") && BeanUtils.isNotEmpty(procDefId)) {
            List<BpmNodeScript> scriptList = bpmNodeScriptDao.queryBpmNodeScript(null,procDefId);
            List<BpmNodeScript> scriptArrayList=new ArrayList<>();
            for (BpmNodeScript script:scriptList) {
                script.setScript(parseScript(script.getScript(), true));
                scriptArrayList.add(script);
            }
            actDefModelXml.setBpmNodeScriptList(scriptArrayList);
        }
        // 流程会签规则
        if (map.get("bpmNodeSign") && BeanUtils.isNotEmpty(procDefId)) {
            List<BpmNodeSign> bpmNodeSignList = bpmNodeSignDao.queryByProcDefId(procDefId);
            actDefModelXml.setBpmNodeSignList(bpmNodeSignList);
        }
        // 流程消息
        if (map.get("bpmNodeMessage") && BeanUtils.isNotEmpty(procDefId)) {
            List<BpmNodeMessage> bpmNodeMessageList = bpmNodeMessageDao.queryByProcDefId(procDefId);
            actDefModelXml.setBpmNodeMessageList(bpmNodeMessageList);
        }
        // 流程变量
        if (map.get("bpmDefVar") && BeanUtils.isNotIncZeroEmpty(modelId) ) {
            List<BpmDefVar> bpmDefVarList = bpmDefVarDao.queryByModelId(modelId);
            actDefModelXml.setBpmDefVarList(bpmDefVarList);
        }
        // 流程节点设置
        if (map.get("bpmNodeSet") && BeanUtils.isNotIncZeroEmpty(modelId) && BeanUtils.isNotEmpty(procDefId)) {
            List<BpmNodeSet> bpmNodeSetList = bpmNodeSetDao.queryAllByProcDefId(procDefId);
            if(StringUtil.isNotEmpty(parentProcDefId)){
                List<BpmNodeSet> parentBpmNodeSets = bpmNodeSetService.queryByProcDefIdAndParentProcDefId(modelId,parentProcDefId,true);
                bpmNodeSetList.addAll(parentBpmNodeSets);
            }
            if(!map.get("formDef")){
                for(BpmNodeSet bpmNodeSet: bpmNodeSetList){
                    bpmNodeSet.setFormKey("");
                    bpmNodeSet.setFormDefName("");
                }
            }
            actDefModelXml.setBpmNodeSetList(bpmNodeSetList);

            if(map.get("bpmNodeUser") && BeanUtils.isNotEmpty(procDefId)){

                // 节点下的人员的配置规则(包含的抄送的设置也导出)
                List<BpmUserCondition> bpmUserConditionList = bpmUserConditionDao.queryByProcDefIdExport(procDefId);
                if (StringUtil.isNotEmpty(parentProcDefId)) {
                    List<BpmUserCondition> bpmUserConditions = bpmUserConditionDao.queryByProcDefIdWithParentProcDefId(procDefId,parentProcDefId);
                    bpmUserConditionList.addAll(bpmUserConditions);
                }
                if (BeanUtils.isNotEmpty(bpmUserConditionList)) {
                    actDefModelXml.setBpmUserConditionList(bpmUserConditionList);
                }

                // 节点下的人员设置
                List<BpmNodeUser> bpmNodeUserList = bpmNodeUserDao.getByProcDefId(procDefId);
                if (StringUtil.isNotEmpty(parentProcDefId)) {
                    List<BpmNodeUser> bpmNodeUsers = bpmNodeUserDao.queryByProcDefIdWithParentProcDefId(procDefId,parentProcDefId);
                    bpmNodeUserList.addAll(bpmNodeUsers);
                }
                if (BeanUtils.isNotEmpty(bpmNodeUserList)) {
                    this.checkBpmNodeUserList(bpmNodeUserList);
                    actDefModelXml.setBpmNodeUserList(bpmNodeUserList);
                }
            }
            // 自定义表单
            if (map.get("formDef") && BeanUtils.isNotEmpty(bpmNodeSetList)) {
                Set<String> tableIdSet = this.exportFormDef(bpmNodeSetList,actDefModelXml);
                // 自定义表
                if (map.get("formTable") && BeanUtils.isNotEmpty(tableIdSet)) {
                    this.exportFormTable(tableIdSet, actDefModelXml);
                }
            }
        }
        // 表单权限
        if(map.get("bpmDefRights") && BeanUtils.isNotEmpty(procDefId)){
            List<FormRights> formRightsList = formRightsDao.queryFormRightsByActDefId(procDefId, PlatformType.undefine.toString());
            if(StringUtil.isNotEmpty(parentProcDefId)){
                List<FormRights> bpmFormRights= formRightsDao.queryFormRightsByActDefIdWithParentActDefId(procDefId,parentProcDefId,PlatformType.undefine.toString());
                formRightsList.addAll(bpmFormRights);
            }
            if (BeanUtils.isNotEmpty(formRightsList)){
                formRightsList = formDefService.exportFormRightsUser(formRightsList);
                actDefModelXml.setFormRightsList(formRightsList);
            }
        }
        // 流程操作按钮设置
        if (map.get("bpmNodeButton") && BeanUtils.isNotIncZeroEmpty(modelId) ) {
            List<BpmNodeButton> bpmNodeButtonList = bpmNodeButtonDao.queryByModelId(modelId);
            actDefModelXml.setBpmNodeButtonList(bpmNodeButtonList);
        }
        // 任务节点催办时间设置
        if (map.get("taskReminder") && BeanUtils.isNotEmpty(procDefId)) {
            List<TaskReminder> taskReminderList = taskReminderDao.queryByProcDefId(procDefId);
            List<TaskReminder> reminderArrayList= new ArrayList<TaskReminder>();
            for (TaskReminder reminder:taskReminderList) {
                reminder.setMailContent(parseScript(reminder.getMailContent(), true));
                reminder.setMsgContent(parseScript(reminder.getMsgContent(), true));
                reminder.setSmsContent(parseScript(reminder.getSmsContent()	, true));
                reminder.setCondExp(parseScript(reminder.getCondExp(), true));
                reminder.setScript(parseScript(reminder.getScript(), true));
                reminderArrayList.add(reminder);
            }
            actDefModelXml.setTaskReminderList(reminderArrayList);
        }
        // 流程联动设置
        if (map.get("bpmGangedSet") && BeanUtils.isNotIncZeroEmpty(modelId)) {
            List<BpmGangedSet> bpmGangedSetList = bpmGangedSetDao.queryByModelId(modelId);
            actDefModelXml.setBpmGangedSetList(bpmGangedSetList);
        }
        /*流程引用设置  已删除该功能*/

        //流程节点SQL.  TODO 待BPM_NODE_SQL表添加后解除注释
//        if (map.get("bpmDefSql") && BeanUtils.isNotEmpty(procDefId)) {
//            List<BpmNodeSql> bpmNodeSqlList = bpmNodeSqlService.queryByNodeIdProcDefIdAndAction(null,procDefId,null);
//            actDefModelXml.setBpmNodeSqlList(bpmNodeSqlList);
//        }
        //触发流程定义。bpmTriggerDef
        if (map.get("bpmTriggerDef") && BeanUtils.isNotEmpty(procDefId)) {
            List<BpmNewFlowTrigger> bpmNewFlowTriggers = bpmNewFlowTriggerService.queryByFlowKey(modelKey);
            actDefModelXml.setBpmTriggerList(bpmNewFlowTriggers);
        }
        //流程消息模版
        if (map.get("nodeMsgTemplate") ) {
            List<NodeMsgTemplate> msgTemplates = msgTemplateService.queryByModelId(modelId);
            actDefModelXml.setMsgTemplates(msgTemplates);
        }

        List<SysFile> sysFileList = new ArrayList<SysFile>();
        // 处理表单附件
        List<BpmFormDefXml> bpmFormDefXmlList = actDefModelXml.getBpmFormDefXmlList();
        if (BeanUtils.isNotEmpty(bpmFormDefXmlList)) {
            for (BpmFormDefXml bpmFormDefXml : bpmFormDefXmlList) {
                if (BeanUtils.isNotEmpty(bpmFormDefXml.getSysFileList())) {
                    sysFileList.addAll(bpmFormDefXml.getSysFileList());
                }
            }
        }
        // 流程帮助
        if (BeanUtils.isNotEmpty(actDefModel.getAttachment())) {
            SysFile sysFile = sysFileService.getOneById(actDefModel.getAttachment());
            if (BeanUtils.isNotEmpty(sysFile)) {
                sysFileList.add(sysFile);
            }
        }
        // 附件
        if (BeanUtils.isNotEmpty(sysFileList)) {
            actDefModelXml.setSysFileList(sysFileList);
            String path = StringUtil
                    .trimSufffix(SysFileService.getBasePath().toString(),
                            File.separator);
            for (SysFile sysFile : sysFileList) {
                this.copySysFile(sysFile, filePath, path);
            }
        }
        return actDefModelXml;
    }

    /**
     * 处理节点人员
     *
     * @param bpmNodeUserList 节点人员列表
     */
    private void checkBpmNodeUserList(List<BpmNodeUser> bpmNodeUserList) {
        for (BpmNodeUser bpmNodeUser : bpmNodeUserList) {
            if (BeanUtils.isEmpty(bpmNodeUser.getAssignType())){    continue;}
            if (BeanUtils.isEmpty(bpmNodeUser.getCmpNames())){      continue;}
            if (BpmNodeUser.ASSIGN_TYPE_USER.equals(bpmNodeUser.getAssignType() ) ) {
                String cmpIds = bpmNodeUser.getCmpIds();
                String[] cmpIdAry = cmpIds.split(",");
                String[] cmpNames = new String[cmpIdAry.length];
                for (int i = 0; i < cmpIdAry.length; i++) {
                    SysUser sysUser = sysUserService.getById(cmpIdAry[i]);
                    if (BeanUtils.isNotEmpty(sysUser)) {
                        cmpNames[i] = sysUser.getAccount();
                    }
                }
                bpmNodeUser.setCmpNames(org.apache.commons.lang.StringUtils.join(cmpNames, ","));
            }
        }
    }

    /**
     * 导出自定义表单
     *
     * @param bpmNodeSetList 节点设置列表
     * @param actDefModelXml actDefModelXml
     * @return 集合
     */
    private Set<String> exportFormDef(List<BpmNodeSet> bpmNodeSetList,ActDefModelXml actDefModelXml) {
        Map<String, Boolean> map = formDefService.getDefaultExportMap(null);
        // 不出现重复的formKey,取得流程定义key
        Set<String> formKeySet = new HashSet<>();
        for (BpmNodeSet bpmNodeSet : bpmNodeSetList) {
            if(StringUtil.isNotEmpty(bpmNodeSet.getFormKey())) {
                formKeySet.add(bpmNodeSet.getFormKey());
            }
        }

        Set<String> tableIdSet = new HashSet<>();
        // 自定义表单
        List<BpmFormDefXml> bpmFormDefXmlList = new ArrayList<>();
        for (String formKey : formKeySet) {
            // 设置自定义表单
            FormDef formDef = formDefDao.getDefaultPublishedByFormKey(formKey);
            String tenantId = ContextUtil.getCurrentUserTenantId();
            formDef.setTenant(tenantId);
            BpmFormDefXml bpmFormDefXml = formDefService.exportBpmFormDef(formDef, FormDef.IS_DEFAULT,map);
            bpmFormDefXmlList.add(bpmFormDefXml);
            // 关联的自定义表ID
            if (BeanUtils.isNotEmpty(formDef)
                    && BeanUtils.isNotIncZeroEmpty(formDef.getTableId())) {
                tableIdSet.add(formDef.getTableId());
            }
        }
        if (BeanUtils.isNotEmpty(bpmFormDefXmlList)) {
            actDefModelXml.setBpmFormDefXmlList(bpmFormDefXmlList);
        }
        return tableIdSet;
    }
    /**
     * 导出自定义表
     *
     * @param tableIdSet 表id
     * @param actDefModelXml actDefModelXml
     */
    private void exportFormTable(Set<String> tableIdSet,ActDefModelXml actDefModelXml) {
        Map<String, Boolean> map = formTableService.getDefaultExportMap(null);
        List<BpmFormTableXml> bpmFormTableXmlList = new ArrayList<>();
        for (String tableId : tableIdSet) {
            FormTable formTable = formTableService.getById(tableId);
            BpmFormTableXml bpmFormTableXml = formTableService.exportTable(
                    formTable, map);
            bpmFormTableXmlList.add(bpmFormTableXml);
        }
        if (BeanUtils.isNotEmpty(bpmFormTableXmlList)) {
            actDefModelXml.setBpmFormTableXmlList(bpmFormTableXmlList);
        }
    }
    /**
     * 导出内（外）部子流程
     *
     * @param actDefModel 模型
     * @param actDefModelXml actDefModelXml
     * @param map map
     */
    private void exportSubActDefModel(ActDefModel actDefModel, ActDefModelXml actDefModelXml, Map<String, Boolean> map, String filePath, String parentProcDefId) {
        String deployId = actDefModel.getDeployId();
        if(BeanUtils.isEmpty(deployId)){    return ;    }
        List<ActDefModelXml> subActDefModelXmlList = new ArrayList<ActDefModelXml>();
        String xml = bpmnXmlService.generateBpmn20Xml(actDefModel);
        Set<String> keySet = NodeCache.getSubKeysByXml(xml);
        for (String procDefKey : keySet) {
            ActDefModel defModel = actDefModelDao.getByProcDefKeyIsMain(procDefKey);
            subActDefModelXmlList.add(exportActDefModel(defModel,ActDefModel.MAIN, map, filePath,parentProcDefId));
        }
        if (BeanUtils.isNotEmpty(subActDefModelXmlList)) {
            actDefModelXml.setSubActDefModelXmlList(subActDefModelXmlList);
        }
    }

    /**
     * 导出流程定义历史版本
     *
     * @param modelId 模型id
     * @param actDefModelXml actDefModelXml
     * @param map map
     */
    private void exportActDefModelHistory(String modelId, ActDefModelXml actDefModelXml, Map<String, Boolean> map, String filePath) {
        Map<String,Object> param = new HashMap<>(1);
        param.put("modelId",modelId);
        param.put("isMain",ActDefModel.NOT_MAIN);
        List<ActDefModel> actDefModelList = this.selectAllHistoryVersions(param);
        if(BeanUtils.isEmpty(actDefModelList)){
            return;
        }
        List<ActDefModelXml> actDefModelXmlList = new ArrayList<ActDefModelXml>(actDefModelList.size());
        for(ActDefModel actDefModel:actDefModelList){
            ActDefModelXml xml = exportActDefModel(actDefModel,ActDefModel.NOT_MAIN,map,filePath,null);
            actDefModelXmlList.add(xml);
        }
        actDefModelXml.setActDefModelXmlList(actDefModelXmlList);
    }

    /**
     * 复制附件到指定文件
     *
     * @param sysFile 文件
     * @param filePath 文件路径
     * @param path      复制路径
     */
    private void copySysFile(SysFile sysFile, String filePath, String path) {
        try {
            String realPath = path + File.separator
                    + sysFile.getFilePath().replace("/", File.separator);
            String fileName = sysFile.getFileId() + "." + sysFile.getExt();
            // 复制到指定文件
            File file = new File(realPath);
            if (file.exists()) {
                filePath = filePath + File.separator + fileName;
                FileUtil.createFolderFile(filePath);
                FileUtil.copyFile(realPath, filePath);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param actDefModel 模型
     * @param flag flag
     * @return ActDefModel
     */
    private ActDefModel parseActDefModel(ActDefModel actDefModel, boolean flag) {
        actDefModel.setModelEditorJson(StringUtil.convertScriptLine(actDefModel.getModelEditorJson(), flag));
        return actDefModel;
    }

    private String parseScript(String script, boolean flag) {
        return StringUtil.convertScriptLine(script,flag);
    }


    /**
     * 导入数据库
     *
     * @param xmlStr xml
     * @param unzipFilePath 路径
     * @param tenantId 租户id
     */
    @Transactional(rollbackFor = Exception.class)
    public void importXml(String xmlStr, String unzipFilePath, String tenantId) throws Exception {
        ActDefModelXmlList actDefModelXmlList = (ActDefModelXmlList) XmlBeanUtil.unmarshall(xmlStr,ActDefModelXmlList.class);
        List<ActDefModelXml> list = actDefModelXmlList.getActDefModelXmlList();

        //保存相关信息
        for(ActDefModelXml actDefModelXml : list){
            ActDefModel actDefModel = actDefModelXml.getActDefModel();
            actDefModelXml.setActDefModel(actDefModel);
            this.importActDefModelXml(actDefModelXml,unzipFilePath,null,tenantId);
        }
    }

    /**
     * 解析相关信息，导入相关list并保存数据库
     * @param actDefModelXml xml
     * @param unzipFilePath 路径
     * @param parentProcDefId 父流程id
     * @param tenantId 租户id
     */
    private void importActDefModelXml(ActDefModelXml actDefModelXml, String unzipFilePath, String parentProcDefId, String tenantId) throws Exception {
        //导入自定义表
        List<BpmFormTableXml> bpmFormTableXmlList = actDefModelXml.getBpmFormTableXmlList();
        if(BeanUtils.isNotEmpty(bpmFormTableXmlList)){
            Set<Identity> identitySet = new HashSet<>();
            for(BpmFormTableXml bpmFormTableXml : bpmFormTableXmlList){
                //导入表，并解析相关信息
                formTableService.importBpmFormTableXml(bpmFormTableXml,tenantId);
                formTableService.setIdentity(bpmFormTableXml.getIdentityList(),identitySet);
            }
            //导入流水号
            formTableService.importIdentity(identitySet);
        }
        List<Map> mapFormKeyList = new ArrayList<>();
        //
        List<Map<Long, Long>> mapFormIdList = new ArrayList<>();
        // 导入自定义表单
        List<BpmFormDefXml> bpmFormDefXmlList = actDefModelXml.getBpmFormDefXmlList();
        if (BeanUtils.isNotEmpty(bpmFormDefXmlList)) {
            for (BpmFormDefXml bpmFormDefXml : bpmFormDefXmlList) {
                String newTabId = formDefService.getTableIdByFormDefFormTable(bpmFormTableXmlList,bpmFormDefXml);
                Map<String, Map> mapForm = formDefService.importBpmFormDef(bpmFormDefXml,newTabId,tenantId);
                Map mapFormKey = mapForm.get("key");
                mapFormKeyList.add(mapFormKey);
                Map<Long, Long> mapFormId = mapForm.get("id");
                mapFormIdList.add(mapFormId);
            }
        }
        // 导入流程定义
        this.importActDefModel(actDefModelXml, mapFormKeyList,mapFormIdList, unzipFilePath,parentProcDefId,tenantId);
    }

    /**
     * 解析相关信息，导入相关list并保存数据库
     *
     * <pre>
     * 导入以下信息:
     * ■ 流程定义 actDefModel
     * ■ 历史版本 actDefModelHistory
     *
     * ■ 流程节点设置 bpmNodeSet
     * ■ 节点下的人员设置  bpmNodeUser
     * ■ 节点下的人员的配置规则 bpmUserCondition
     * ■ 节点下的人员上下级设置 bpmNodeUserUplow
     *
     * ■ 流程定义权限 bpmDefRights
     * ■ 常用语设置 taskApprovalItems
     *
     * ■ 流程跳转规则  bpmNodeRule
     * ■ 流程事件脚本  bpmNodeScript
     *
     * ■ 流程操作按钮设置 bpmNodeButton
     * ■ 流程变量  bpmDefVar
     *
     * ■ 流程消息  bpmNodeMessage
     * ■ 流程会签规则  bpmNodeSign
     *
     * ■ 任务节点催办时间设置 taskReminder
     * ■ 内（外）部子流程 subActDefModel
     * </pre>
     *
     * @param actDefModelXml xml
     * @param mapFormKeyList 表单key
     * @param mapFormIdList 表单kid
     * @param unzipFilePath 路径
     * @param parentProcDefId 父流程id
     * @param tenantId 租户id
     */
    private void importActDefModel(ActDefModelXml actDefModelXml, List<Map> mapFormKeyList, List<Map<Long, Long>> mapFormIdList, String unzipFilePath, String parentProcDefId, String tenantId) throws Exception {
        //附件
        List<SysFile> sysFileList = actDefModelXml.getSysFileList();
        if(BeanUtils.isNotEmpty(sysFileList)){
            this.importSysFile(sysFileList,unzipFilePath);
        }
        ActDefModel actDefModel = actDefModelXml.getActDefModel();
        //流程定义
        actDefModel = this.importActDefModel(actDefModel,tenantId);
        String procDefId = actDefModel.getProcDefId();
        String modelId   = actDefModel.getId();

        //子流程
        List<ActDefModelXml> subActDefModelXmlList = actDefModelXml.getSubActDefModelXmlList();
        if(BeanUtils.isNotEmpty(subActDefModelXmlList)){
            for (ActDefModelXml defModelXml : subActDefModelXmlList){
                this.importActDefModelXml(defModelXml,unzipFilePath,procDefId,tenantId);
            }
        }

        //表单权限
        List<FormRights> formRightsList = actDefModelXml.getFormRightsList();
        if(BeanUtils.isNotEmpty(formRightsList)){
            this.importFormRights(formRightsList,mapFormKeyList,procDefId,parentProcDefId);
        }

        //流程跳转规则
        List<BpmNodeRule> bpmNodeRuleList = actDefModelXml.getBpmNodeRuleList();
        if(BeanUtils.isNotEmpty(bpmNodeRuleList)){
            this.importBpmNodeRule(bpmNodeRuleList,procDefId);
        }

        //流程事件脚本
        List<BpmNodeScript> bpmNodeScriptList = actDefModelXml.getBpmNodeScriptList();
        if(BeanUtils.isNotEmpty(bpmNodeScriptList)){
            this.importBpmNodeScript(bpmNodeScriptList,procDefId);
        }

        //流程变量
        List<BpmDefVar> bpmDefVarList=actDefModelXml.getBpmDefVarList();
        if(BeanUtils.isNotEmpty(bpmDefVarList)){
            this.importBpmDefVar(bpmDefVarList,modelId);
        }

        //流程会签规则
        List<BpmNodeSign> bpmNodeSignList = actDefModelXml.getBpmNodeSignList();
        if(BeanUtils.isNotEmpty(bpmNodeSignList)){
            this.importBpmNodeSign(bpmNodeSignList,procDefId);
        }

        //流程消息模板
        List<BpmNodeMessage> bpmNodeMessageList = actDefModelXml.getBpmNodeMessageList();
        if(BeanUtils.isNotEmpty(bpmNodeMessageList)){
            this.improtBpmNodeMessage(bpmNodeMessageList,procDefId);
        }

        //导入节点的相关信息（包含：节点，节点人员条件，节点人员）
        this.importBpmNodeSet(actDefModelXml,modelId,procDefId,mapFormIdList,parentProcDefId);

        //常用语设置(仅限于导入对于流程的常用语设置)
        List<TaskApprovalItems> taskApprovalItemsList = actDefModelXml.getTaskApprovalItemsList();
        if(BeanUtils.isNotEmpty(taskApprovalItemsList)){
            this.importTaskApprovalItems(taskApprovalItemsList,actDefModel.getModelKey());
        }

        //流程操作按钮
        List<BpmNodeButton> bpmNodeButtonList = actDefModelXml.getBpmNodeButtonList();
        if(BeanUtils.isNotEmpty(bpmNodeButtonList)){
            this.importBpmNodeButton(bpmNodeButtonList,modelId,procDefId);
        }

        //任务节点催办事件设置
        List<TaskReminder> taskReminderList = actDefModelXml.getTaskReminderList();
        if(BeanUtils.isNotEmpty(taskReminderList)){
            this.importTaskReminder(taskReminderList,procDefId);
        }

        //流程联动设置
        List<BpmGangedSet> bpmGangedSetList = actDefModelXml.getBpmGangedSetList();
        if(BeanUtils.isNotEmpty(bpmGangedSetList)){
            this.importBpmGangedSet(bpmGangedSetList,modelId);
        }

        //导入SQL
        List<BpmNodeSql> bpmNodeSqlList = actDefModelXml.getBpmNodeSqlList();
        if(BeanUtils.isNotEmpty(bpmNodeSqlList)){
            this.importBpmNodeSql(bpmNodeSqlList,procDefId);
        }

        //导入节点模板
        List<NodeMsgTemplate> msgTemplateList = actDefModelXml.getMsgTemplates();
        if(BeanUtils.isNotEmpty(msgTemplateList)){
            this.importNodeMsgTemplate(msgTemplateList,modelId);
        }

        //触发新流程
        List<BpmNewFlowTrigger> bpmNewFlowTriggerList = actDefModelXml.getBpmTriggerList();
        if(BeanUtils.isNotEmpty(bpmNewFlowTriggerList)){
            this.importBpmNewFlowTrigger(bpmNewFlowTriggerList);
        }

        /*流程引用功能去除*/

    }

    /**
     * 导入附件
     *
     * @param sysFileList 文件列表
     * @param unzipFilePath 路径
     */
    private void importSysFile(List<SysFile> sysFileList, String unzipFilePath) {
        String realPath = StringUtil.trimSufffix(SysFileService.getBasePath(), File.separator);
        for (SysFile sysFile : sysFileList) {
            String id = sysFile.getFileId();
            SysFile file = sysFileService.getOneById(id);
            sysFile = this.parseSysFile(sysFile, realPath, unzipFilePath);
            if (BeanUtils.isEmpty(file)) {
                //多租户 added by caosl 2017-5-10
                String tenantId = ContextUtil.getCurrentUserTenantId();
                sysFile.setTenantId(tenantId);
                sysFileService.add(sysFile);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "附件,ID:" + id + ",该记录成功导入!");
            } else {
                BeanUtils.copyNotNullProperties(file, sysFile);
                file.setCreatetime(sysFile.getCreatetime());
                sysFileService.update(file);
                MsgUtil.addMsg(MsgUtil.WARN, "附件,ID:" + id + "已经存在,该记录进行更新!");
            }
        }
    }

    /**
     * 处理附件
     *
     * @param sysFile 文件
     * @param realPath 实际路径
     * @param unzipFilePath 解压路径
     * @return 文件
     */
    private SysFile parseSysFile(SysFile sysFile, String realPath, String unzipFilePath) {
        SysUser sysUser = (SysUser) ContextUtil.getCurrentUser();
        sysFile.setCreatorId(sysUser.getUserId());
        sysFile.setCreator(sysUser.getAccount());

        this.copyToSysFile(sysFile, realPath, unzipFilePath);
        return sysFile;
    }

    /**
     * 把文件复制到指定路径
     * @param sysFile 文件
     * @param realPath 实际路径
     * @param unzipFilePath 解压路径
     */
    private void copyToSysFile(SysFile sysFile, String realPath, String unzipFilePath) {
        try {
            realPath = realPath + File.separator+ sysFile.getFilePath().replace("/", File.separator);
            String fileName = sysFile.getFileId() + "." + sysFile.getExt();
            String filePath = unzipFilePath + fileName;
            // 复制到指定文件
            File file = new File(filePath);
            if (file.exists()) {
                FileUtil.createFolderFile(realPath);
                FileUtil.copyFile(filePath, realPath);
            } else {
                MsgUtil.addMsg(MsgUtil.ERROR, "导入附件中不存在:" + fileName + ",请检查!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 导入流程定义
     *
     * @param actDefModel 模型
     * @param tenantId 租户id
     * @return 模型
     */
    private ActDefModel importActDefModel(ActDefModel actDefModel, String tenantId) {
        // 处理xml
        actDefModel = parseActDefModel(actDefModel, false);
        this.saveActDefModel(actDefModel,tenantId);
        return actDefModel;
    }

    /**
     * 保存及更新流程定义
     *
     * @param actDefModel 模型
     * @param tenantId 租户id
     */
    private void saveActDefModel(ActDefModel actDefModel, String tenantId) {
        ActDefModel defModel = getMainByDefKey(actDefModel.getModelKey());
        String newId=UUIDUtils.getUUIDFor32();
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        BpmnModel bpmnModel = getBpmnModel(actDefModel);
        Deployment deployment = deploymentBuilder.addBpmnModel(actDefModel.getName() + StringPool.SUFFIX_BPMN, bpmnModel)
                .name(actDefModel.getName()).key(actDefModel.getModelKey()).category(actDefModel.getTypeId()).deploy();

        ProcessDefinitionEntity ent = bpmService.getProcessActDefModelByDeployId(deployment.getId());
        // 设置分类
        actDefModel = this.setTypeId(actDefModel);
        // 未发布流程导入时，重新设置当前用户为流程创建人
        if (actDefModel.getStatus()==0) {
            actDefModel = this.setAuthor(actDefModel);
        }
        if (BeanUtils.isEmpty(defModel)) {
            actDefModel.setId(newId);
            actDefModel.setDeployId(deployment.getId());
            actDefModel.setProcDefId(ent.getId());
            actDefModel.setProcDefKey(ent.getKey());
            actDefModel.setUpdateTime(new Date());
            actDefModel.setIsMain(ActDefModel.MAIN);
            actDefModel.setVersion(1);
            actDefModel.setTenantId(tenantId);
            add(actDefModel);
            MsgUtil.addMsg(MsgUtil.SUCCESS, "流程定义:" + actDefModel.getName() + ",该记录成功导入！");
        } else {
            this.updateSubVersions(actDefModel.getModelKey(),newId);
            actDefModel.setId(newId);
            actDefModel.setDeployId(deployment.getId());
            actDefModel.setProcDefId(ent.getId());
            actDefModel.setProcDefKey(ent.getKey());
            actDefModel.setUpdateTime(new Date());
            actDefModel.setIsMain(ActDefModel.MAIN);
            actDefModel.setVersion(ent.getVersion());
            actDefModel.setTenantId(tenantId);
            add(actDefModel);
            MsgUtil.addMsg(MsgUtil.WARN, "流程定义:" + actDefModel.getName() + ",已经存在,重新发布新版本!");
        }
    }

    /**
     * 设置流程拥有者
     *
     * @param actDefModel 模型
     * @return 模型
     */
    private ActDefModel setAuthor(ActDefModel actDefModel) {
        actDefModel.setCreateBy(ContextUtil.getCurrentUserId());
        return actDefModel;
    }

    /**
     * 设置分类
     *
     * @param actDefModel 模型
     * @return 模型
     */
    private ActDefModel setTypeId(ActDefModel actDefModel) {
        if (BeanUtils.isEmpty(actDefModel.getTypeId())) {
            return actDefModel;
        }
        GlobalType globalType = globalTypeDao.getById(actDefModel.getTypeId());
        if (BeanUtils.isEmpty(globalType)) {
            actDefModel.setTypeId(null);
        }
        return actDefModel;
    }

    /**
     * 导入表单权限
     *
     * @param formRightsList 权限list
     * @param mapFormKeyList 表单key
     * @param procDefId 定义id
     * @param parentProcDefId 父流程定义id
     */
    private void importFormRights(List<FormRights> formRightsList, List<Map> mapFormKeyList, String procDefId, String parentProcDefId) {
        formRightsDao.delByActDefIdExcNode(procDefId,0);
        for (FormRights formRights : formRightsList) {
            String formKey = getFormKey(mapFormKeyList,formRights.getFormKey());
            if (BeanUtils.isEmpty(formKey)) {
                continue;
            }
            this.importFormRights(formRights, formKey, procDefId,parentProcDefId);
        }

    }

    /**
     *
     *
     * @param mapFormKeyList 表单key列表
     * @param formKey  表单key
     * @return String
     */
    private String getFormKey(List<Map> mapFormKeyList, String formKey) {
        String deseFormKey = null;
        for (Map map : mapFormKeyList) {
            deseFormKey = map.get(formKey)==null?"":map.get(formKey).toString();
            if (BeanUtils.isNotEmpty(deseFormKey)) {
                break;
            }
        }
        return deseFormKey;
    }

    /**
     * 保存 表单权限
     *
     * @param formRights 表单权限
     * @param formKey 表单key
     * @param procDefId 流程定义id
     * @param parentProcDefId 父流程定义id
     */
    private void importFormRights(FormRights formRights, String formKey, String procDefId, String parentProcDefId) {
        formRights.setFormKey(formKey);
        formRights.setActDefId(procDefId);
        if (StringUtil.isNotEmpty(formRights.getParentActDefId())) {
            formRights.setParentActDefId(parentProcDefId);
        }
        if(formRights.getType() != FormRights.TABLE_SHOW_RIGHTS) {
            formRights.setPermission(formDefService.parsePermission(formRights.getPermission(), false));
        }
        //	如果只是更新流程表单权限，这将会导致之前版本的流程表单权限控制不了
        formRights.setId(UUIDUtils.getUUIDFor32());
        formRightsDao.add(formRights);
        MsgUtil.addMsg(MsgUtil.SUCCESS," 表单权限:表单权限ID:" + formRights.getId() + ",该记录成功导入!");
    }

    /**
     * 导入流程跳转规则
     *
     * @param bpmNodeRuleList 规则list
     * @param procDefId 流程定义id
     */
    private void importBpmNodeRule(List<BpmNodeRule> bpmNodeRuleList, String procDefId) {
        for (BpmNodeRule bpmNodeRule : bpmNodeRuleList) {
            String id = bpmNodeRule.getRuleId();
            bpmNodeRule.setConditionCode(parseScript(bpmNodeRule.getConditionCode(), false));
            BpmNodeRule nodeRule = bpmNodeRuleDao.getById(id);
            if (BeanUtils.isEmpty(nodeRule)) {
                bpmNodeRule.setProcDefId(procDefId);
                bpmNodeRuleDao.add(bpmNodeRule);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "流程跳转规则,ID:" + id + ",该记录成功导入！");
            } else {
                bpmNodeRule.setRuleId(UUIDUtils.getUUIDFor32());
                bpmNodeRule.setProcDefId(procDefId);
                bpmNodeRuleDao.add(bpmNodeRule);
                MsgUtil.addMsg(MsgUtil.WARN, "流程跳转规则,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入流程事件脚本
     *
     * @param bpmNodeScriptList 脚本list
     * @param procDefId 流程定义id
     */
    private void importBpmNodeScript(List<BpmNodeScript> bpmNodeScriptList, String procDefId) {
        for (BpmNodeScript bpmNodeScript : bpmNodeScriptList) {
            String id = bpmNodeScript.getId();
            bpmNodeScript.setScript(parseScript(bpmNodeScript.getScript(), false));
            BpmNodeScript nodeScript = bpmNodeScriptDao.getById(id);
            if (BeanUtils.isEmpty(nodeScript)) {
                bpmNodeScript.setProcDefId(procDefId);
                bpmNodeScriptDao.add(bpmNodeScript);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "流程事件脚本,ID:" + id + ",该记录成功导入！");
            } else {
                bpmNodeScript.setId(UUIDUtils.getUUIDFor32());
                bpmNodeScript.setProcDefId(procDefId);
                bpmNodeScriptDao.add(bpmNodeScript);
                MsgUtil.addMsg(MsgUtil.WARN, "流程事件脚本,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入流程变量
     *
     * @param bpmDefVarList 流程变量list
     * @param modelId 模型id
     */
    private void importBpmDefVar(List<BpmDefVar> bpmDefVarList, String modelId) {
        for (BpmDefVar bpmDefVar : bpmDefVarList) {
            String id = bpmDefVar.getVarId();
            BpmDefVar defVar = bpmDefVarDao.getById(id);
            if (BeanUtils.isEmpty(defVar)) {
                bpmDefVar.setModelId(modelId);
                bpmDefVarDao.add(bpmDefVar);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "流程变量,ID:" + id + ",该记录成功导入！");
            } else {
                bpmDefVar.setVarId(UUIDUtils.getUUIDFor32());
                bpmDefVar.setModelId(modelId);
                bpmDefVarDao.add(bpmDefVar);
                MsgUtil.addMsg(MsgUtil.WARN, "流程变量,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入流程会签规则
     *
     * @param bpmNodeSignList 会签规则list
     * @param procDefId 流程定义id
     */
    private void importBpmNodeSign(List<BpmNodeSign> bpmNodeSignList, String procDefId) {
        for (BpmNodeSign bpmNodeSign : bpmNodeSignList) {
            String id = bpmNodeSign.getSignId();
            BpmNodeSign nodeSign = bpmNodeSignDao.getById(id);
            if (BeanUtils.isEmpty(nodeSign)) {
                bpmNodeSign.setProcDefId(procDefId);
                bpmNodeSignDao.add(bpmNodeSign);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "流程会签规则,ID:" + id + ",该记录成功导入！");
            } else {
                bpmNodeSign.setSignId(UUIDUtils.getUUIDFor32());
                bpmNodeSign.setProcDefId(procDefId);
                bpmNodeSignDao.add(bpmNodeSign);
                MsgUtil.addMsg(MsgUtil.WARN, "流程会签规则,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入流程消息设置
     *
     * @param bpmNodeMessageList 消息设置list
     * @param procDefId 流程定义id
     */
    private void improtBpmNodeMessage(List<BpmNodeMessage> bpmNodeMessageList, String procDefId) {
        for (BpmNodeMessage bpmNodeMessage : bpmNodeMessageList) {
            String id = bpmNodeMessage.getId();
            BpmNodeMessage nodeMessage = bpmNodeMessageDao.getById(id);
            if (BeanUtils.isEmpty(nodeMessage)) {
                bpmNodeMessage.setProcDefId(procDefId);
                bpmNodeMessageDao.add(bpmNodeMessage);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "流程消息设置,ID:" + id + ",该记录成功导入！");
            } else {
                bpmNodeMessage.setId(UUIDUtils.getUUIDFor32());
                bpmNodeMessage.setProcDefId(procDefId);
                bpmNodeMessageDao.add(bpmNodeMessage);
                MsgUtil.addMsg(MsgUtil.WARN, "流程消息设置,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入节点的相关信息
     * 具体信息：
     * bpmNodeSet           流程节点设置
     * bpmUserCondition     流程节点人员规则设置
     * bpmNodeUser          流程节点人员设置
     * bpmNodeUserUplow     用户节点的上下级
     *
     * @param actDefModelXml xml
     * @param modelId 模型id
     * @param procDefId 流程定义id
     * @param mapFormIdList 表单id
     * @param parentProcDefId 父流程id
     */
    private void importBpmNodeSet(ActDefModelXml actDefModelXml, String modelId, String procDefId, List<Map<Long, Long>> mapFormIdList, String parentProcDefId) {
        //流程节点设置
        List<BpmNodeSet> bpmNodeSetList = actDefModelXml.getBpmNodeSetList();
        //流程节点人员辅助设置
        List<BpmNodeUser> bpmNodeUserList = actDefModelXml.getBpmNodeUserList();
        //流程节点人员规则设置
        List<BpmUserCondition> bpmUserConditionList = actDefModelXml.getBpmUserConditionList();

        // 执行人员规则
        List<BpmUserCondition> userConditionList = new ArrayList<>();
        // 抄送人员规则
        List<BpmUserCondition> copyToUserConditionList = new ArrayList<>();
        // 其他类型人员规则
        List<BpmUserCondition> otherUserConditionList = new ArrayList<>();
        //流程人员规则赋值
        if (BeanUtils.isNotEmpty(bpmUserConditionList)) {
            for (BpmUserCondition bpmUserCondition : bpmUserConditionList) {
                if (bpmUserCondition.getConditionType().shortValue() == BpmUserCondition.CONDITION_TYPE_EXEUSER){
                    //执行人员规则
                    userConditionList.add(bpmUserCondition);
                }else if (bpmUserCondition.getConditionType().shortValue() == BpmUserCondition.CONDITION_TYPE_COPYUSER){
                    //抄送人员规则
                    copyToUserConditionList.add(bpmUserCondition);
                }else{
                    //其他类型人员规则
                    otherUserConditionList.add(bpmUserCondition);
                }

            }
        }

       /*原代码位置，移至下方 【bpmNodeUser的执行or抄送人员分类循环赋值】*/

        //导入节点、规则条件、人员辅助设置
        if (BeanUtils.isNotEmpty(bpmNodeSetList)) {
            for (BpmNodeSet nodeSet : bpmNodeSetList) {
                String origSetId = nodeSet.getSetId();
                //节点设置
                String destSetId = this.importBpmNodeSet(nodeSet, procDefId, origSetId, parentProcDefId);
                //规则设置
                for (BpmUserCondition condition : userConditionList) {
                    if (BeanUtils.isEmpty(condition.getSetId())) {
                        continue;
                    }
                    if (origSetId.equals(condition.getSetId())) {
                        String conditionId = this.importBpmUserCondition(condition, procDefId, destSetId, parentProcDefId);
                        //保存执行人员对应的新conditionId
                        condition.setOldId(conditionId);
                    }
                }
            }
        }

        //保存抄送人员对应的新conditionId
        if(BeanUtils.isNotEmpty(copyToUserConditionList)){
            this.saveBpmUserConditionOldId(copyToUserConditionList,procDefId,null,parentProcDefId);
        }
        //保存其他类型人员对应的新conditionId
        if(BeanUtils.isNotEmpty(otherUserConditionList)){
            this.saveBpmUserConditionOldId(otherUserConditionList,procDefId,null,parentProcDefId);
        }


        /*新增加oldId属性后，移至此处【bpmNodeUser的执行or抄送人员分类循环赋值】*/


        //节点人员
        List<BpmNodeUser> nodeUserList = new ArrayList<>();
        //抄送人员
        List<BpmNodeUser> copyToBpmNodeUserList = new ArrayList<>();
        //流程人员设置赋值
        if (BeanUtils.isNotEmpty(bpmNodeUserList)) {
            for (BpmNodeUser user : bpmNodeUserList) {
                boolean isBreak = false;
                //执行人员赋值
                for (BpmUserCondition condition : userConditionList) {
                    //新增oldId后，跟据oldId进行判断再将id赋值给conditionId，确保数据正确更新
                    if (user.getConditionId().equals(condition.getOldId())) {
                        user.setConditionId(condition.getId());
                        nodeUserList.add(user);
                        isBreak = true;
                        break;
                    }
                }
                if (!isBreak) {
                    //抄送人员赋值
                    for (BpmUserCondition copyToCondition : copyToUserConditionList) {
                        if (user.getConditionId().equals(copyToCondition.getOldId())) {
                            user.setConditionId(copyToCondition.getId());
                            copyToBpmNodeUserList.add(user);
                            break;
                        }
                    }
                }
            }
        }

        //执行人员
        if(BeanUtils.isNotEmpty(nodeUserList)){
            this.importBpmNodeUser(nodeUserList,procDefId);
        }
        //抄送人员
        if(BeanUtils.isNotEmpty(copyToUserConditionList)){
            this.importBpmNodeUser(copyToBpmNodeUserList,procDefId);
        }

    }

    /**
     * 导入流程人员设置
     *
     * @param nodeUserList 人员list
     * @param procDefId 流程定义id
     */
    private void importBpmNodeUser(List<BpmNodeUser> nodeUserList, String procDefId) {
        for(BpmNodeUser bpmNodeUser : nodeUserList) {
            //导入默认设置
            bpmNodeUser = this.parseBpmNodeUser(bpmNodeUser);

            String id = bpmNodeUser.getNodeUserId();
            BpmNodeUser nodeUser = bpmNodeUserDao.getById(id);
            if (BeanUtils.isEmpty(nodeUser)) {
                bpmNodeUserDao.add(bpmNodeUser);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "人员设置,ID:" + id + ",该记录成功导入!");
            } else {
                bpmNodeUser.setNodeUserId(UUIDUtils.getUUIDFor32());
                bpmNodeUserDao.add(bpmNodeUser);
                MsgUtil.addMsg(MsgUtil.WARN, "人员设置,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 解析流程节点人员
     *
     * @param bpmNodeUser 人员
     * @return BpmNodeUser
     */
    private BpmNodeUser parseBpmNodeUser(BpmNodeUser bpmNodeUser) {
        String cmpName = bpmNodeUser.getCmpNames();
        if (StringUtil.isEmpty(cmpName)) {
            return bpmNodeUser;
        }
        String[] cmpNamesAry = cmpName.split(",");
        String msg = "人员设置";
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(0, bpmNodeUser.getCmpIds());
        map.put(1, bpmNodeUser.getCmpNames());
        // 0,9,10,11,13不需要检查设置
        String assignType=bpmNodeUser.getAssignType();
        if ( BpmNodeUser.ASSIGN_TYPE_USER.equals(assignType)) {
            // 用户1
            map = this.parseSysUser(cmpNamesAry, msg);
        } else if ( BpmNodeUser.ASSIGN_TYPE_ROLE.equals(assignType)) {
            // 角色2
            map = this.parseSysRole(cmpNamesAry, msg);
        } else if (BpmNodeUser.ASSIGN_TYPE_ORG.equals(assignType)  ) {
            // 组织3
            map = this.parseSysOrg(cmpNamesAry, msg);
        } else if ( BpmNodeUser.ASSIGN_TYPE_ORG_CHARGE.equals(assignType) ) {
            // 组织负责人4
            map = this.parseSysOrg(cmpNamesAry, msg);
        } else if (BpmNodeUser.ASSIGN_TYPE_POS.equals(assignType) ) {
            // 岗位5
            map = this.parsePosition(cmpNamesAry, msg);
        }
        bpmNodeUser.setCmpIds(map.get(0));
        bpmNodeUser.setCmpNames(map.get(1));
        return bpmNodeUser;
    }

    /**
     * 解析用户
     *
     * @param cmpNamesAry cmpNamesAry
     * @param msg 消息
     * @return map
     */
    private Map<Integer, String> parseSysUser(String[] cmpNamesAry, String msg) {
        Map<Integer, String> map = new HashMap<>(15);
        String cmpIds = "";
        String cmpNames = "";
        for (String name : cmpNamesAry) {
            SysUser sysUser = sysUserService.getByAccount(name);
            if (BeanUtils.isEmpty(sysUser)) {
                MsgUtil.addMsg(MsgUtil.ERROR, msg + "中的用户工号：" + name + ",不存在!请检查!");
                continue;
            } else {
                cmpIds += sysUser.getUserId() + ",";
                cmpNames += sysUser.getFullName() + ",";
            }
        }
        return this.trimInfo(map, cmpIds, cmpNames);
    }

    /**
     * 解析角色
     *
     * @param cmpNamesAry
     *            名称数组
     * @param msg
     *            提示消息
     * @return map
     */
    private Map<Integer, String> parseSysRole(String[] cmpNamesAry, String msg) {
        Map<Integer, String> map = new HashMap<>(15);
        String cmpIds = "";
        String cmpNames = "";
        for (String name : cmpNamesAry) {
            List<SysRole> sysRoleList =sysRoleService.queryByRoleName(name);
            if (BeanUtils.isEmpty(sysRoleList)) {
                MsgUtil.addMsg(MsgUtil.ERROR, msg + "中的角色名称：" + name
                        + ",不存在!请检查!");
            } else if (sysRoleList.size() > 1) {
                MsgUtil.addMsg(MsgUtil.ERROR, msg + "中的角色名称：" + name
                        + ",多于一条记录!请检查!");
            } else {
                SysRole sysRole = (SysRole)sysRoleList.get(0);
                cmpIds += sysRole.getRoleId() + ",";
                cmpNames += sysRole.getRoleName() + ",";
            }
        }

        return this.trimInfo(map, cmpIds, cmpNames);
    }

    /**
     * 解析组织
     *
     * @param cmpNamesAry
     *            名称数组
     * @param msg
     *            提示消息
     * @return map
     */
    private Map<Integer, String> parseSysOrg(String[] cmpNamesAry, String msg) {
        Map<Integer, String> map = new HashMap<>(15);
        String cmpIds = "";
        String cmpNames = "";
        for (String name : cmpNamesAry) {
            List<SysOrg> sysOrgList = sysOrgService.queryByOrgName(name);
            if (BeanUtils.isEmpty(sysOrgList)) {
                MsgUtil.addMsg(MsgUtil.ERROR, msg + "中的组织名称：" + name + ",不存在!请检查!");
            } else if (sysOrgList.size() > 1) {
                MsgUtil.addMsg(MsgUtil.ERROR, msg + "中的组织名称：" + name + ",多于一条记录!请检查!");
            } else {
                SysOrg sysOrg = sysOrgList.get(0);
                cmpIds += sysOrg.getOrgId() + ",";
                cmpNames += sysOrg.getOrgName() + ",";
            }
        }
        return this.trimInfo(map, cmpIds, cmpNames);
    }

    /**
     * 解析岗位
     *
     * @param cmpNamesAry
     *            名称数组
     * @param msg
     *            提示消息
     * @return map
     */
    private Map<Integer, String> parsePosition(String[] cmpNamesAry, String msg) {
        Map<Integer, String> map = new HashMap<>(15);
        String cmpIds = "";
        String cmpNames = "";
        for (String name : cmpNamesAry) {
            List<Position> positionList = positionService.queryByPosName(name);
            if (BeanUtils.isEmpty(positionList)) {
                MsgUtil.addMsg(MsgUtil.ERROR, msg + "中的岗位名称：" + name + ",不存在!请检查!");
            } else if (positionList.size() > 1) {
                MsgUtil.addMsg(MsgUtil.ERROR, msg + "中的岗位名称：" + name + ",多于一条记录!请检查!");
            } else {
                Position position = positionList.get(0);
                cmpIds += position.getPosId() + ",";
                cmpNames += position.getPosName() + ",";
            }
        }
        return this.trimInfo(map, cmpIds, cmpNames);
    }

    /**
     *
     * @param map map
     * @param cmpIds cmpIds
     * @param cmpNames cmpNames
     * @return map
     */
    private Map<Integer, String> trimInfo(Map<Integer, String> map,
                                          String cmpIds, String cmpNames) {
        if (cmpIds.length() > 0) {
            cmpIds = cmpIds.substring(0, cmpIds.length() - 1);
        }
        if (cmpNames.length() > 0) {
            cmpNames = cmpNames.substring(0, cmpNames.length() - 1);
        }
        map.put(0, cmpIds);
        map.put(1, cmpNames);
        return map;
    }

    /**
     * 人员设置导入
     *
     * @param bpmUserConditionList 人员条件
     * @param procDefId 定义id
     * @param destSetId 目标节点id
     * @param parentProcDefId 父定义id
     */
    private void saveBpmUserConditionOldId(List<BpmUserCondition> bpmUserConditionList, String procDefId,String destSetId, String parentProcDefId) {
        for(BpmUserCondition bpmUserCondition : bpmUserConditionList){
            String conditionId     = this.importBpmUserCondition(bpmUserCondition,procDefId,destSetId,parentProcDefId);
            bpmUserCondition.setOldId(conditionId);
        }
    }

    /**
     * 导入流程人员规则设置
     *
     * @param bpmUserCondition 人员条件
     * @param procDefId 定义id
     * @param destSetId 目标节点id
     * @param parentProcDefId 父定义id
     * @return String
     */
    private String importBpmUserCondition(BpmUserCondition bpmUserCondition, String procDefId, String destSetId, String parentProcDefId) {
        //默认导入设置
        bpmUserCondition.setProcDefId(procDefId);
        bpmUserCondition.setSetId(destSetId);

        String id =bpmUserCondition.getId();
        BpmUserCondition userCondition = bpmUserConditionDao.getById(id);
        if(BeanUtils.isEmpty(userCondition)){
            bpmUserConditionDao.add(bpmUserCondition);
            MsgUtil.addMsg(MsgUtil.SUCCESS, "流程人员规则设置,ID:" + id + ",该记录成功导入！");
        }else{
            bpmUserCondition.setId(UUIDUtils.getUUIDFor32());
            bpmUserConditionDao.add(bpmUserCondition);
            MsgUtil.addMsg(MsgUtil.WARN, "流程人员规则设置,ID:" + id + "已经存在,重新发布新版本！");
        }
        return id;
    }

    /**
     * 导入流程节点设置
     *
     * @param bpmNodeSet 节点设置
     * @param procDefId 定义id
     * @param origSetId 原始节点id
     * @param parentProcDefId 父id
     * @return String
     */
    private String importBpmNodeSet(BpmNodeSet bpmNodeSet,String procDefId, String origSetId, String parentProcDefId) {
        //默认导入设置
        bpmNodeSet.setProcDefId(procDefId);
        if(StringUtil.isEmpty(bpmNodeSet.getFormKey())){
            bpmNodeSet.setFormType(BpmNodeSet.FORMTYPE_DEFAULT);
        }

        if(StringUtil.isNotEmpty(bpmNodeSet.getParentProcDefId())){
            bpmNodeSet.setParentProcDefId(parentProcDefId);
        }

        BpmNodeSet nodeSet = bpmNodeSetDao.getByProcDefIdNodeIdForImport(procDefId,bpmNodeSet.getNodeId());
        if(BeanUtils.isEmpty(nodeSet)){
            BpmNodeSet set = bpmNodeSetDao.getById(bpmNodeSet.getSetId());
            if(BeanUtils.isEmpty(set)){
                bpmNodeSetDao.add(bpmNodeSet);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "流程节点设置,ID:" + origSetId + ",该记录成功导入！");
            }else {
                bpmNodeSet.setSetId(UUIDUtils.getUUIDFor32());
                bpmNodeSetDao.add(bpmNodeSet);
                MsgUtil.addMsg(MsgUtil.WARN, "流程节点设置,ID:" + origSetId + "已经存在,完成数据更新！");
            }
        }else{
            //导入流程设计器时，除去全局节点其他节点都已生成，此处进行检查数据修正
            bpmNodeSet.setSetId(nodeSet.getSetId());
            bpmNodeSetDao.update(bpmNodeSet);
            MsgUtil.addMsg(MsgUtil.SUCCESS, "流程节点设置,ID:" + origSetId + ",该记录成功导入！");
        }
        return bpmNodeSet.getSetId();
    }

    /**
     * 导入常用语设置(但仅限于导入对于该流程的常用语设置)
     *
     * @param list 常用语list
     * @param modelKey 模型key
     */
    private void importTaskApprovalItems(List<TaskApprovalItems> list,String modelKey){
        for(TaskApprovalItems taskApprovalItems : list){
            //默认导入设置
            taskApprovalItems.setModelKey(modelKey);
            taskApprovalItems.setType(TaskApprovalItems.TYPE_FLOW);

            String id = taskApprovalItems.getItemId();
            TaskApprovalItems approvalItems = taskApprovalItemsService.getById(id);
            if(BeanUtils.isEmpty(approvalItems)){
                taskApprovalItemsService.add(taskApprovalItems);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "常用语设置,ID:" + id + ",该记录成功导入！");
            }else{
                taskApprovalItems.setItemId(UUIDUtils.getUUIDFor32());
                taskApprovalItemsService.add(taskApprovalItems);
                MsgUtil.addMsg(MsgUtil.WARN, "常用语设置,ID:" + id + "已经存在,重新发布新版本！");
            }
        }
    }
    /**
     * 导入流程操作按钮
     * @param bpmNodeButtonList 操作按钮
     * @param modelId 模型id
     * @param procDefId 定义id
     */
    private void importBpmNodeButton(List<BpmNodeButton> bpmNodeButtonList, String modelId, String procDefId) {
        for (BpmNodeButton bpmNodeButton : bpmNodeButtonList) {
            //默认导入设置
            bpmNodeButton.setModelId(modelId);
            bpmNodeButton.setProcDefId(procDefId);

            String id = bpmNodeButton.getId();
            BpmNodeButton nodeButton = bpmNodeButtonDao.getById(id);
            if (BeanUtils.isEmpty(nodeButton)) {
                bpmNodeButtonDao.add(bpmNodeButton);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "流程操作按钮设置,ID:" + id + ",该记录成功导入！");
            } else {
                bpmNodeButton.setId(UUIDUtils.getUUIDFor32());
                bpmNodeButtonDao.add(bpmNodeButton);
                MsgUtil.addMsg(MsgUtil.WARN, "流程操作按钮设置,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入任务节点催办时间设置
     *
     * @param taskReminderList 催办list
     * @param procDefId 定义id
     */
    private void importTaskReminder(List<TaskReminder> taskReminderList, String procDefId) throws Exception {
        for (TaskReminder taskReminder : taskReminderList) {
            //默认导入设置
            taskReminder.setMailContent(parseScript(taskReminder.getMailContent(), false));
            taskReminder.setMsgContent(parseScript(taskReminder.getMsgContent(), false));
            taskReminder.setSmsContent(parseScript(taskReminder.getSmsContent()	, false));
            taskReminder.setCondExp(parseScript(taskReminder.getCondExp(), false));
            taskReminder.setScript(parseScript(taskReminder.getScript(), false));
            taskReminder.setProcDefId(procDefId);

            String id = taskReminder.getTaskDueId();
            TaskReminder reminder = taskReminderDao.getById(id);
            if (BeanUtils.isEmpty(reminder)) {
                taskReminderDao.add(taskReminder);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "任务节点催办时间设置,ID:" + id + ",该记录成功导入！");
            } else {
                taskReminder.setTaskDueId(UUIDUtils.getUUIDFor32());
                taskReminderDao.add(taskReminder);
                MsgUtil.addMsg(MsgUtil.WARN, "任务节点催办时间设置,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入流程联动设置
     *
     * @param bpmGangedSetList 联动设置list
     * @param modelId 模型id
     */
    private void importBpmGangedSet(List<BpmGangedSet> bpmGangedSetList,String modelId) {
        for (BpmGangedSet bpmGangedSet : bpmGangedSetList) {
            //默认导入设置
            bpmGangedSet.setModelId(modelId);

            String id = bpmGangedSet.getId();
            BpmGangedSet gangedSet = bpmGangedSetDao.getById(id);
            if (BeanUtils.isEmpty(gangedSet)) {
                bpmGangedSetDao.add(bpmGangedSet);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "流程联动设置,ID:" + id + ",该记录成功导入!");
            } else {
                bpmGangedSet.setId(UUIDUtils.getUUIDFor32());
                bpmGangedSetDao.add(bpmGangedSet);
                MsgUtil.addMsg(MsgUtil.WARN, "流程联动设置,ID:" + id + "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入BpmNodeSql数据。
     * @param bpmNodeSqlList sql列表
     * @param procDefId 流程定义id
     */
    private void importBpmNodeSql(List<BpmNodeSql> bpmNodeSqlList,String procDefId) {

        for (BpmNodeSql bpmNodeSql : bpmNodeSqlList) {
            //默认导入设置
            bpmNodeSql.setProcDefId(procDefId);

            String id = bpmNodeSql.getId();
            BpmNodeSql  nodeSql= bpmNodeSqlService.getOneById(id);
            if (BeanUtils.isEmpty(nodeSql)) {
                bpmNodeSqlService.add(bpmNodeSql);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "BpmNodeSql,ID:" + id + ",该记录成功导入!");
            } else {
                bpmNodeSql.setId(UUIDUtils.getUUIDFor32());
                bpmNodeSql.setProcDefId(procDefId);
                bpmNodeSqlService.add(bpmNodeSql);
                MsgUtil.addMsg(MsgUtil.WARN, "BpmNodeSql,ID:" + id + "已经存在,重新发布新版本!");
            }
        }

    }

    /**
     * 导入节点模板
     *
     * @param msgTemplateList 节点消息模板
     * @param modelId 模型id
     */
    private void importNodeMsgTemplate(List<NodeMsgTemplate> msgTemplateList, String modelId) {
        for (NodeMsgTemplate msgTemplate : msgTemplateList) {
            if(StringUtil.isEmpty(msgTemplate.getParentDefId())){
                continue;
            }
            //默认导入设置
            msgTemplate.setDefId(modelId);

            String id = msgTemplate.getId();
            NodeMsgTemplate  template= msgTemplateService.getOneById(id);
            if (BeanUtils.isNotEmpty(template)) {
                msgTemplateService.add(msgTemplate);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "NodeMsgTemplate,ID:" + id + ",该记录成功导入!");
            } else {
                msgTemplate.setId(UUIDUtils.getUUIDFor32());
                msgTemplateService.add(msgTemplate);
                MsgUtil.addMsg(MsgUtil.WARN, "NodeMsgTemplate,ID:" + id+ "已经存在,重新发布新版本!");
            }
        }
    }

    /**
     * 导入触发新流程
     *
     * @param bpmNewFlowTriggerList 触发新流程list
     */
    private void importBpmNewFlowTrigger(List<BpmNewFlowTrigger> bpmNewFlowTriggerList) {
        for (BpmNewFlowTrigger flowTrigger : bpmNewFlowTriggerList){
            String id = flowTrigger.getId();
            BpmNewFlowTrigger trigger = bpmNewFlowTriggerService.getOneById(id);
            if(BeanUtils.isEmpty(trigger)){
                bpmNewFlowTriggerService.add(flowTrigger);
                MsgUtil.addMsg(MsgUtil.SUCCESS, "BpmNewFlowTrigger,ID:" + id + ",该记录成功导入!");
            } else {
                flowTrigger.setId(UUIDUtils.getUUIDFor32());
                bpmNewFlowTriggerService.add(flowTrigger);
                MsgUtil.addMsg(MsgUtil.WARN, "BpmNewFlowTrigger,ID:" + id + "已经存在,重新发布新版本!");
            }

        }
    }
}
